compile-time evaluation: emit a lint when a write through an immutable pointer occurs
This commit is contained in:
@@ -9,8 +9,9 @@ use std::hash::Hash;
|
||||
use rustc_apfloat::{Float, FloatConvert};
|
||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::query::TyCtxtAt;
|
||||
use rustc_middle::ty;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_target::abi::{Align, Size};
|
||||
use rustc_target::spec::abi::Abi as CallAbi;
|
||||
@@ -293,7 +294,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
||||
/// `def_id` is `Some` if this is the "lazy" allocation of a static.
|
||||
#[inline]
|
||||
fn before_access_global(
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
_tcx: TyCtxtAt<'tcx>,
|
||||
_machine: &Self,
|
||||
_alloc_id: AllocId,
|
||||
_allocation: ConstAllocation<'tcx>,
|
||||
@@ -388,7 +389,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
||||
/// need to mutate.
|
||||
#[inline(always)]
|
||||
fn before_memory_read(
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
_tcx: TyCtxtAt<'tcx>,
|
||||
_machine: &Self,
|
||||
_alloc_extra: &Self::AllocExtra,
|
||||
_prov: (AllocId, Self::ProvenanceExtra),
|
||||
@@ -400,7 +401,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
||||
/// Hook for performing extra checks on a memory write access.
|
||||
#[inline(always)]
|
||||
fn before_memory_write(
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
_tcx: TyCtxtAt<'tcx>,
|
||||
_machine: &mut Self,
|
||||
_alloc_extra: &mut Self::AllocExtra,
|
||||
_prov: (AllocId, Self::ProvenanceExtra),
|
||||
@@ -412,7 +413,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
||||
/// Hook for performing extra operations on a memory deallocation.
|
||||
#[inline(always)]
|
||||
fn before_memory_deallocation(
|
||||
_tcx: TyCtxt<'tcx>,
|
||||
_tcx: TyCtxtAt<'tcx>,
|
||||
_machine: &mut Self,
|
||||
_alloc_extra: &mut Self::AllocExtra,
|
||||
_prov: (AllocId, Self::ProvenanceExtra),
|
||||
@@ -515,7 +516,7 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
|
||||
/// (CTFE and ConstProp) use the same instance. Here, we share that code.
|
||||
pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
||||
type Provenance = CtfeProvenance;
|
||||
type ProvenanceExtra = (); // FIXME extract the "immutable" bool?
|
||||
type ProvenanceExtra = bool; // the "immutable" flag
|
||||
|
||||
type ExtraFnVal = !;
|
||||
|
||||
@@ -597,6 +598,6 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
|
||||
) -> Option<(AllocId, Size, Self::ProvenanceExtra)> {
|
||||
// We know `offset` is relative to the allocation, so we can use `into_parts`.
|
||||
let (prov, offset) = ptr.into_parts();
|
||||
Some((prov.alloc_id(), offset, ()))
|
||||
Some((prov.alloc_id(), offset, prov.immutable()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +339,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
// Let the machine take some extra action
|
||||
let size = alloc.size();
|
||||
M::before_memory_deallocation(
|
||||
*self.tcx,
|
||||
self.tcx,
|
||||
&mut self.machine,
|
||||
&mut alloc.extra,
|
||||
(alloc_id, prov),
|
||||
@@ -561,7 +561,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
(val, Some(def_id))
|
||||
}
|
||||
};
|
||||
M::before_access_global(*self.tcx, &self.machine, id, alloc, def_id, is_write)?;
|
||||
M::before_access_global(self.tcx, &self.machine, id, alloc, def_id, is_write)?;
|
||||
// We got tcx memory. Let the machine initialize its "extra" stuff.
|
||||
M::adjust_allocation(
|
||||
self,
|
||||
@@ -626,7 +626,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
)?;
|
||||
if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc {
|
||||
let range = alloc_range(offset, size);
|
||||
M::before_memory_read(*self.tcx, &self.machine, &alloc.extra, (alloc_id, prov), range)?;
|
||||
M::before_memory_read(self.tcx, &self.machine, &alloc.extra, (alloc_id, prov), range)?;
|
||||
Ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id }))
|
||||
} else {
|
||||
// Even in this branch we have to be sure that we actually access the allocation, in
|
||||
@@ -687,13 +687,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
{
|
||||
let parts = self.get_ptr_access(ptr, size)?;
|
||||
if let Some((alloc_id, offset, prov)) = parts {
|
||||
let tcx = *self.tcx;
|
||||
let tcx = self.tcx;
|
||||
// FIXME: can we somehow avoid looking up the allocation twice here?
|
||||
// We cannot call `get_raw_mut` inside `check_and_deref_ptr` as that would duplicate `&mut self`.
|
||||
let (alloc, machine) = self.get_alloc_raw_mut(alloc_id)?;
|
||||
let range = alloc_range(offset, size);
|
||||
M::before_memory_write(tcx, machine, &mut alloc.extra, (alloc_id, prov), range)?;
|
||||
Ok(Some(AllocRefMut { alloc, range, tcx, alloc_id }))
|
||||
Ok(Some(AllocRefMut { alloc, range, tcx: *tcx, alloc_id }))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
@@ -1133,7 +1133,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let src_alloc = self.get_alloc_raw(src_alloc_id)?;
|
||||
let src_range = alloc_range(src_offset, size);
|
||||
M::before_memory_read(
|
||||
*tcx,
|
||||
tcx,
|
||||
&self.machine,
|
||||
&src_alloc.extra,
|
||||
(src_alloc_id, src_prov),
|
||||
@@ -1163,7 +1163,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
||||
let (dest_alloc, extra) = self.get_alloc_raw_mut(dest_alloc_id)?;
|
||||
let dest_range = alloc_range(dest_offset, size * num_copies);
|
||||
M::before_memory_write(
|
||||
*tcx,
|
||||
tcx,
|
||||
extra,
|
||||
&mut dest_alloc.extra,
|
||||
(dest_alloc_id, dest_prov),
|
||||
|
||||
Reference in New Issue
Block a user