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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue