Introduce ConstAllocation
.
Currently some `Allocation`s are interned, some are not, and it's very hard to tell at a use point which is which. This commit introduces `ConstAllocation` for the known-interned ones, which makes the division much clearer. `ConstAllocation::inner()` is used to get the underlying `Allocation`. In some places it's natural to use an `Allocation`, in some it's natural to use a `ConstAllocation`, and in some places there's no clear choice. I've tried to make things look as nice as possible, while generally favouring `ConstAllocation`, which is the type that embodies more information. This does require quite a few calls to `inner()`. The commit also tweaks how `PartialOrd` works for `Interned`. The previous code was too clever by half, building on `T: Ord` to make the code shorter. That caused problems with deriving `PartialOrd` and `Ord` for `ConstAllocation`, so I changed it to build on `T: PartialOrd`, which is slightly more verbose but much more standard and avoided the problems.
This commit is contained in:
parent
c38b8a8c62
commit
4852291417
30 changed files with 166 additions and 119 deletions
|
@ -367,7 +367,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
|
|||
"the raw bytes of the constant ({}",
|
||||
display_allocation(
|
||||
*ecx.tcx,
|
||||
ecx.tcx.global_alloc(alloc_id).unwrap_memory()
|
||||
ecx.tcx.global_alloc(alloc_id).unwrap_memory().inner()
|
||||
)
|
||||
));
|
||||
},
|
||||
|
|
|
@ -18,8 +18,8 @@ use rustc_target::abi::{Align, Size};
|
|||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use crate::interpret::{
|
||||
self, compile_time_machine, AllocId, Allocation, Frame, ImmTy, InterpCx, InterpResult, OpTy,
|
||||
PlaceTy, Scalar, StackPopUnwind,
|
||||
self, compile_time_machine, AllocId, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
|
||||
OpTy, PlaceTy, Scalar, StackPopUnwind,
|
||||
};
|
||||
|
||||
use super::error::*;
|
||||
|
@ -475,13 +475,14 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
fn before_access_global(
|
||||
memory_extra: &MemoryExtra,
|
||||
alloc_id: AllocId,
|
||||
allocation: &Allocation,
|
||||
alloc: ConstAllocation<'tcx>,
|
||||
static_def_id: Option<DefId>,
|
||||
is_write: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
let alloc = alloc.inner();
|
||||
if is_write {
|
||||
// Write access. These are never allowed, but we give a targeted error message.
|
||||
if allocation.mutability == Mutability::Not {
|
||||
if alloc.mutability == Mutability::Not {
|
||||
Err(err_ub!(WriteToReadOnly(alloc_id)).into())
|
||||
} else {
|
||||
Err(ConstEvalErrKind::ModifiedGlobal.into())
|
||||
|
@ -504,7 +505,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
|
|||
// But make sure we never accept a read from something mutable, that would be
|
||||
// unsound. The reason is that as the content of this allocation may be different
|
||||
// now and at run-time, so if we permit reading now we might return the wrong value.
|
||||
assert_eq!(allocation.mutability, Mutability::Not);
|
||||
assert_eq!(alloc.mutability, Mutability::Not);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -183,7 +183,7 @@ pub(crate) fn deref_const<'tcx>(
|
|||
let mplace = ecx.deref_operand(&op).unwrap();
|
||||
if let Some(alloc_id) = mplace.ptr.provenance {
|
||||
assert_eq!(
|
||||
tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().mutability,
|
||||
tcx.get_global_alloc(alloc_id).unwrap().unwrap_memory().inner().mutability,
|
||||
Mutability::Not,
|
||||
"deref_const cannot be used with mutable allocations as \
|
||||
that could allow pattern matching to observe mutable statics",
|
||||
|
|
|
@ -23,7 +23,10 @@ use rustc_middle::ty::{self, layout::TyAndLayout, Ty};
|
|||
|
||||
use rustc_ast::Mutability;
|
||||
|
||||
use super::{AllocId, Allocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy, ValueVisitor};
|
||||
use super::{
|
||||
AllocId, Allocation, ConstAllocation, InterpCx, MPlaceTy, Machine, MemoryKind, PlaceTy,
|
||||
ValueVisitor,
|
||||
};
|
||||
use crate::const_eval;
|
||||
|
||||
pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
|
||||
|
@ -131,8 +134,8 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx, const_eval:
|
|||
alloc.mutability = Mutability::Not;
|
||||
};
|
||||
// link the alloc id to the actual allocation
|
||||
let alloc = tcx.intern_const_alloc(alloc);
|
||||
leftover_allocations.extend(alloc.relocations().iter().map(|&(_, alloc_id)| alloc_id));
|
||||
let alloc = tcx.intern_const_alloc(alloc);
|
||||
tcx.set_alloc_id_memory(alloc_id, alloc);
|
||||
None
|
||||
}
|
||||
|
@ -393,7 +396,7 @@ pub fn intern_const_alloc_recursive<
|
|||
}
|
||||
let alloc = tcx.intern_const_alloc(alloc);
|
||||
tcx.set_alloc_id_memory(alloc_id, alloc);
|
||||
for &(_, alloc_id) in alloc.relocations().iter() {
|
||||
for &(_, alloc_id) in alloc.inner().relocations().iter() {
|
||||
if leftover_allocations.insert(alloc_id) {
|
||||
todo.push(alloc_id);
|
||||
}
|
||||
|
@ -425,7 +428,7 @@ impl<'mir, 'tcx: 'mir, M: super::intern::CompileTimeMachine<'mir, 'tcx, !>>
|
|||
&mut InterpCx<'mir, 'tcx, M>,
|
||||
&PlaceTy<'tcx, M::PointerTag>,
|
||||
) -> InterpResult<'tcx, ()>,
|
||||
) -> InterpResult<'tcx, &'tcx Allocation> {
|
||||
) -> InterpResult<'tcx, ConstAllocation<'tcx>> {
|
||||
let dest = self.allocate(layout, MemoryKind::Stack)?;
|
||||
f(self, &dest.into())?;
|
||||
let mut alloc = self.memory.alloc_map.remove(&dest.ptr.provenance.unwrap()).unwrap().1;
|
||||
|
|
|
@ -56,7 +56,7 @@ crate fn eval_nullary_intrinsic<'tcx>(
|
|||
sym::type_name => {
|
||||
ensure_monomorphic_enough(tcx, tp_ty)?;
|
||||
let alloc = type_name::alloc_type_name(tcx, tp_ty);
|
||||
ConstValue::Slice { data: alloc, start: 0, end: alloc.len() }
|
||||
ConstValue::Slice { data: alloc, start: 0, end: alloc.inner().len() }
|
||||
}
|
||||
sym::needs_drop => {
|
||||
ensure_monomorphic_enough(tcx, tp_ty)?;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_hir::def_id::CrateNum;
|
||||
use rustc_hir::definitions::DisambiguatedDefPathData;
|
||||
use rustc_middle::mir::interpret::Allocation;
|
||||
use rustc_middle::mir::interpret::{Allocation, ConstAllocation};
|
||||
use rustc_middle::ty::{
|
||||
self,
|
||||
print::{PrettyPrinter, Print, Printer},
|
||||
|
@ -188,7 +188,7 @@ impl Write for AbsolutePathPrinter<'_> {
|
|||
}
|
||||
|
||||
/// Directly returns an `Allocation` containing an absolute path representation of the given type.
|
||||
crate fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation {
|
||||
crate fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAllocation<'tcx> {
|
||||
let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
|
||||
let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes());
|
||||
tcx.intern_const_alloc(alloc)
|
||||
|
|
|
@ -13,8 +13,9 @@ use rustc_target::abi::Size;
|
|||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use super::{
|
||||
AllocId, AllocRange, Allocation, Frame, ImmTy, InterpCx, InterpResult, LocalValue, MemPlace,
|
||||
Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar, StackPopUnwind,
|
||||
AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx, InterpResult,
|
||||
LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
|
||||
StackPopUnwind,
|
||||
};
|
||||
|
||||
/// Data returned by Machine::stack_pop,
|
||||
|
@ -252,7 +253,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
|
|||
fn before_access_global(
|
||||
_memory_extra: &Self::MemoryExtra,
|
||||
_alloc_id: AllocId,
|
||||
_allocation: &Allocation,
|
||||
_allocation: ConstAllocation<'tcx>,
|
||||
_static_def_id: Option<DefId>,
|
||||
_is_write: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
|
|
|
@ -525,12 +525,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||
}
|
||||
};
|
||||
M::before_access_global(&self.extra, id, alloc, def_id, is_write)?;
|
||||
let alloc = Cow::Borrowed(alloc);
|
||||
// We got tcx memory. Let the machine initialize its "extra" stuff.
|
||||
let alloc = M::init_allocation_extra(
|
||||
self,
|
||||
id, // always use the ID we got as input, not the "hidden" one.
|
||||
alloc,
|
||||
Cow::Borrowed(alloc.inner()),
|
||||
M::GLOBAL_KIND.map(MemoryKind::Machine),
|
||||
);
|
||||
Ok(alloc)
|
||||
|
@ -711,6 +710,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||
Some(GlobalAlloc::Memory(alloc)) => {
|
||||
// Need to duplicate the logic here, because the global allocations have
|
||||
// different associated types than the interpreter-local ones.
|
||||
let alloc = alloc.inner();
|
||||
Ok((alloc.size(), alloc.align))
|
||||
}
|
||||
Some(GlobalAlloc::Function(_)) => bug!("We already checked function pointers above"),
|
||||
|
@ -867,7 +867,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> std::fmt::Debug for DumpAllocs<'a,
|
|||
&mut *fmt,
|
||||
self.mem.tcx,
|
||||
&mut allocs_to_print,
|
||||
alloc,
|
||||
alloc.inner(),
|
||||
)?;
|
||||
}
|
||||
Some(GlobalAlloc::Function(func)) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue