diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 52c72de7579..f82af62c5f3 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -458,7 +458,7 @@ fn from(ptr: Pointer) -> Self { } } -#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable, HashStable, Hash)] pub enum ScalarMaybeUndef { Scalar(Scalar), Undef, diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 68bb0a3e435..f3c503b2970 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -3,22 +3,34 @@ //! After a const evaluation has computed a value, before we destroy the const evaluator's session //! memory, we need to extract all memory allocations to the global memory pool so they stay around. -use rustc::ty::{Ty, self}; -use rustc::mir::interpret::{InterpResult, ErrorHandled}; -use rustc::hir; use super::validity::RefTracking; -use rustc_data_structures::fx::FxHashSet; +use rustc::hir; +use rustc::mir::interpret::{ErrorHandled, InterpResult}; +use rustc::ty::{self, Ty}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use syntax::ast::Mutability; use super::{ - ValueVisitor, MemoryKind, AllocId, MPlaceTy, Scalar, + AllocId, Allocation, InterpCx, Machine, MemoryKind, MPlaceTy, Scalar, ValueVisitor, }; -use crate::const_eval::{CompileTimeInterpreter, CompileTimeEvalContext}; -struct InternVisitor<'rt, 'mir, 'tcx> { +struct InternVisitor<'rt, 'mir, 'tcx, M> +where + M: Machine< + 'mir, + 'tcx, + MemoryKinds = !, + PointerTag = (), + ExtraFnVal = !, + FrameExtra = (), + MemoryExtra = (), + AllocExtra = (), + MemoryMap = FxHashMap, Allocation)>, + >, +{ /// The ectx from which we intern. - ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>, + ecx: &'rt mut InterpCx<'mir, 'tcx, M>, /// Previously encountered safe references. ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>, /// A list of all encountered allocations. After type-based interning, we traverse this list to @@ -58,18 +70,28 @@ enum InternMode { /// `immutable` things might become mutable if `ty` is not frozen. /// `ty` can be `None` if there is no potential interior mutability /// to account for (e.g. for vtables). -fn intern_shallow<'rt, 'mir, 'tcx>( - ecx: &'rt mut CompileTimeEvalContext<'mir, 'tcx>, +fn intern_shallow<'rt, 'mir, 'tcx, M>( + ecx: &'rt mut InterpCx<'mir, 'tcx, M>, leftover_allocations: &'rt mut FxHashSet, mode: InternMode, alloc_id: AllocId, mutability: Mutability, ty: Option>, -) -> InterpResult<'tcx, Option> { - trace!( - "InternVisitor::intern {:?} with {:?}", - alloc_id, mutability, - ); +) -> InterpResult<'tcx, Option> +where + M: Machine< + 'mir, + 'tcx, + MemoryKinds = !, + PointerTag = (), + ExtraFnVal = !, + FrameExtra = (), + MemoryExtra = (), + AllocExtra = (), + MemoryMap = FxHashMap, Allocation)>, + >, +{ + trace!("InternVisitor::intern {:?} with {:?}", alloc_id, mutability,); // remove allocation let tcx = ecx.tcx; let (kind, mut alloc) = match ecx.memory.alloc_map.remove(&alloc_id) { @@ -130,7 +152,20 @@ fn intern_shallow<'rt, 'mir, 'tcx>( Ok(None) } -impl<'rt, 'mir, 'tcx> InternVisitor<'rt, 'mir, 'tcx> { +impl<'rt, 'mir, 'tcx, M> InternVisitor<'rt, 'mir, 'tcx, M> +where + M: Machine< + 'mir, + 'tcx, + MemoryKinds = !, + PointerTag = (), + ExtraFnVal = !, + FrameExtra = (), + MemoryExtra = (), + AllocExtra = (), + MemoryMap = FxHashMap, Allocation)>, + >, +{ fn intern_shallow( &mut self, alloc_id: AllocId, @@ -148,15 +183,27 @@ fn intern_shallow( } } -impl<'rt, 'mir, 'tcx> - ValueVisitor<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> +impl<'rt, 'mir, 'tcx, M> + ValueVisitor<'mir, 'tcx, M> for - InternVisitor<'rt, 'mir, 'tcx> + InternVisitor<'rt, 'mir, 'tcx, M> +where + M: Machine< + 'mir, + 'tcx, + MemoryKinds = !, + PointerTag = (), + ExtraFnVal = !, + FrameExtra = (), + MemoryExtra = (), + AllocExtra = (), + MemoryMap = FxHashMap, Allocation)>, + >, { type V = MPlaceTy<'tcx>; #[inline(always)] - fn ecx(&self) -> &CompileTimeEvalContext<'mir, 'tcx> { + fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> { &self.ecx } @@ -265,12 +312,25 @@ fn visit_primitive(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> { } } -pub fn intern_const_alloc_recursive( - ecx: &mut CompileTimeEvalContext<'mir, 'tcx>, +pub fn intern_const_alloc_recursive( + ecx: &mut InterpCx<'mir, 'tcx, M>, // The `mutability` of the place, ignoring the type. place_mut: Option, ret: MPlaceTy<'tcx>, -) -> InterpResult<'tcx> { +) -> InterpResult<'tcx> +where + M: Machine< + 'mir, + 'tcx, + MemoryKinds = !, + PointerTag = (), + ExtraFnVal = !, + FrameExtra = (), + MemoryExtra = (), + AllocExtra = (), + MemoryMap = FxHashMap, Allocation)>, + >, +{ let tcx = ecx.tcx; let (base_mutability, base_intern_mode) = match place_mut { Some(hir::Mutability::Immutable) => (Mutability::Immutable, InternMode::Static), diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index cfa70164cdc..1a01baccabf 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -27,7 +27,7 @@ /// operations and fat pointers. This idea was taken from rustc's codegen. /// In particular, thanks to `ScalarPair`, arithmetic operations and casts can be entirely /// defined on `Immediate`, and do not have to work with a `Place`. -#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)] pub enum Immediate { Scalar(ScalarMaybeUndef), ScalarPair(ScalarMaybeUndef, ScalarMaybeUndef), @@ -104,7 +104,7 @@ fn deref(&self) -> &Immediate { /// An `Operand` is the result of computing a `mir::Operand`. It can be immediate, /// or still in memory. The latter is an optimization, to delay reading that chunk of /// memory and to avoid having to store arbitrary-sized data here. -#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable, Hash)] pub enum Operand { Immediate(Immediate), Indirect(MemPlace), @@ -134,7 +134,7 @@ pub fn assert_immediate(self) -> Immediate } } -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub struct OpTy<'tcx, Tag=()> { op: Operand, // Keep this private, it helps enforce invariants pub layout: TyLayout<'tcx>,