Skip to content

Commit 683db73

Browse files
committed
use associated const for machine controlling mutable statics
So get rid of the IsStatic trait again
1 parent a827507 commit 683db73

File tree

5 files changed

+39
-67
lines changed

5 files changed

+39
-67
lines changed

src/librustc_mir/const_eval.rs

+4-22
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ use syntax::source_map::Span;
2626

2727
use rustc::mir::interpret::{
2828
EvalResult, EvalError, EvalErrorKind, GlobalId,
29-
Scalar, AllocId, Allocation, ConstValue, AllocType,
29+
Scalar, Allocation, ConstValue,
3030
};
3131
use interpret::{self,
3232
Place, PlaceTy, MemPlace, OpTy, Operand, Value,
33-
EvalContext, StackPopCleanup, MemoryKind, Memory,
33+
EvalContext, StackPopCleanup, MemoryKind,
3434
};
3535

3636
pub fn mk_borrowck_eval_cx<'a, 'mir, 'tcx>(
@@ -232,17 +232,12 @@ impl Error for ConstEvalError {
232232
}
233233
}
234234

235-
impl interpret::IsStatic for ! {
236-
fn is_static(self) -> bool {
237-
// unreachable
238-
self
239-
}
240-
}
241-
242235
impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeEvaluator {
243236
type MemoryData = ();
244237
type MemoryKinds = !;
245238

239+
const MUT_STATIC_KIND: Option<!> = None; // no mutating of statics allowed
240+
246241
fn find_fn<'a>(
247242
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
248243
instance: ty::Instance<'tcx>,
@@ -308,19 +303,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeEvaluator {
308303
}
309304
}
310305

311-
fn access_static_mut<'a, 'm>(
312-
mem: &'m mut Memory<'a, 'mir, 'tcx, Self>,
313-
id: AllocId,
314-
) -> EvalResult<'tcx, &'m mut Allocation> {
315-
// This is always an error, we do not allow mutating statics
316-
match mem.tcx.alloc_map.lock().get(id) {
317-
Some(AllocType::Memory(..)) |
318-
Some(AllocType::Static(..)) => err!(ModifiedConstantMemory),
319-
Some(AllocType::Function(..)) => err!(DerefFunctionPointer),
320-
None => err!(DanglingPointerDeref),
321-
}
322-
}
323-
324306
fn find_foreign_static<'a>(
325307
_tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
326308
_def_id: DefId,

src/librustc_mir/interpret/machine.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,11 @@
1515
use std::hash::Hash;
1616

1717
use rustc::hir::def_id::DefId;
18-
use rustc::mir::interpret::{AllocId, Allocation, EvalResult, Scalar};
18+
use rustc::mir::interpret::{Allocation, EvalResult, Scalar};
1919
use rustc::mir;
2020
use rustc::ty::{self, layout::TyLayout, query::TyCtxtAt};
2121

22-
use super::{EvalContext, PlaceTy, OpTy, Memory};
23-
24-
/// Used by the machine to tell if a certain allocation is for static memory
25-
pub trait IsStatic {
26-
fn is_static(self) -> bool;
27-
}
22+
use super::{EvalContext, PlaceTy, OpTy};
2823

2924
/// Methods of this trait signifies a point where CTFE evaluation would fail
3025
/// and some use case dependent behaviour can instead be applied
@@ -33,7 +28,10 @@ pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash {
3328
type MemoryData: Clone + Eq + Hash;
3429

3530
/// Additional memory kinds a machine wishes to distinguish from the builtin ones
36-
type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq + Hash + IsStatic;
31+
type MemoryKinds: ::std::fmt::Debug + Copy + Clone + Eq + Hash;
32+
33+
/// The memory kind to use for mutated statics -- or None if those are not supported.
34+
const MUT_STATIC_KIND: Option<Self::MemoryKinds>;
3735

3836
/// Entry point to all function calls.
3937
///
@@ -63,6 +61,9 @@ pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash {
6361
) -> EvalResult<'tcx>;
6462

6563
/// Called for read access to a foreign static item.
64+
/// This can be called multiple times for the same static item and should return consistent
65+
/// results. Once the item is *written* the first time, as usual for statics a copy is
66+
/// made and this function is not called again.
6667
fn find_foreign_static<'a>(
6768
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
6869
def_id: DefId,
@@ -83,12 +84,6 @@ pub trait Machine<'mir, 'tcx>: Clone + Eq + Hash {
8384
right_layout: TyLayout<'tcx>,
8485
) -> EvalResult<'tcx, Option<(Scalar, bool)>>;
8586

86-
/// Called when requiring mutable access to data in a static.
87-
fn access_static_mut<'a, 'm>(
88-
mem: &'m mut Memory<'a, 'mir, 'tcx, Self>,
89-
id: AllocId,
90-
) -> EvalResult<'tcx, &'m mut Allocation>;
91-
9287
/// Heap allocations via the `box` keyword
9388
///
9489
/// Returns a pointer to the allocated memory

src/librustc_mir/interpret/memory.rs

+24-29
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use rustc_data_structures::fx::{FxHashSet, FxHashMap, FxHasher};
2929

3030
use syntax::ast::Mutability;
3131

32-
use super::{Machine, IsStatic};
32+
use super::Machine;
3333

3434
#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
3535
pub enum MemoryKind<T> {
@@ -39,23 +39,16 @@ pub enum MemoryKind<T> {
3939
Machine(T),
4040
}
4141

42-
impl<T: IsStatic> IsStatic for MemoryKind<T> {
43-
fn is_static(self) -> bool {
44-
match self {
45-
MemoryKind::Stack => false,
46-
MemoryKind::Machine(kind) => kind.is_static(),
47-
}
48-
}
49-
}
50-
5142
#[derive(Clone)]
5243
pub struct Memory<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'mir, 'tcx>> {
5344
/// Additional data required by the Machine
5445
pub data: M::MemoryData,
5546

5647
/// Allocations local to this instance of the miri engine. The kind
5748
/// helps ensure that the same mechanism is used for allocation and
58-
/// deallocation.
49+
/// deallocation. When an allocation is not found here, it is a
50+
/// static and looked up in the `tcx` for read access. Writing to
51+
/// a static creates a copy here, in the machine.
5952
alloc_map: FxHashMap<AllocId, (MemoryKind<M::MemoryKinds>, Allocation)>,
6053

6154
pub tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
@@ -223,10 +216,6 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
223216
Ok(new_ptr)
224217
}
225218

226-
pub fn is_static(&self, alloc_id: AllocId) -> bool {
227-
self.alloc_map.get(&alloc_id).map_or(true, |&(kind, _)| kind.is_static())
228-
}
229-
230219
/// Deallocate a local, or do nothing if that local has been made into a static
231220
pub fn deallocate_local(&mut self, ptr: Pointer) -> EvalResult<'tcx> {
232221
// The allocation might be already removed by static interning.
@@ -354,10 +343,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
354343
/// Allocation accessors
355344
impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
356345
pub fn get(&self, id: AllocId) -> EvalResult<'tcx, &Allocation> {
357-
// normal alloc?
358346
match self.alloc_map.get(&id) {
347+
// Normal alloc?
359348
Some(alloc) => Ok(&alloc.1),
360-
// No need to make any copies, just provide read access to the global static
349+
// Static. No need to make any copies, just provide read access to the global static
361350
// memory in tcx.
362351
None => const_eval_static::<M>(self.tcx, id),
363352
}
@@ -368,14 +357,18 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
368357
id: AllocId,
369358
) -> EvalResult<'tcx, &mut Allocation> {
370359
// Static?
371-
let alloc = if self.alloc_map.contains_key(&id) {
372-
&mut self.alloc_map.get_mut(&id).unwrap().1
373-
} else {
374-
// The machine controls to what extend we are allowed to mutate global
375-
// statics. (We do not want to allow that during CTFE, but miri needs it.)
376-
M::access_static_mut(self, id)?
377-
};
378-
// See if we can use this
360+
if !self.alloc_map.contains_key(&id) {
361+
// Ask the machine for what to do
362+
if let Some(kind) = M::MUT_STATIC_KIND {
363+
// The machine supports mutating statics. Make a copy, use that.
364+
self.deep_copy_static(id, MemoryKind::Machine(kind))?;
365+
} else {
366+
return err!(ModifiedConstantMemory)
367+
}
368+
}
369+
// If we come here, we know the allocation is in our map
370+
let alloc = &mut self.alloc_map.get_mut(&id).unwrap().1;
371+
// See if we are allowed to mutate this
379372
if alloc.mutability == Mutability::Immutable {
380373
err!(ModifiedConstantMemory)
381374
} else {
@@ -489,10 +482,12 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
489482

490483
pub fn leak_report(&self) -> usize {
491484
trace!("### LEAK REPORT ###");
485+
let mut_static_kind = M::MUT_STATIC_KIND.map(|k| MemoryKind::Machine(k));
492486
let leaks: Vec<_> = self.alloc_map
493487
.iter()
494-
.filter_map(|(&id, (kind, _))|
495-
if kind.is_static() { None } else { Some(id) } )
488+
.filter_map(|(&id, &(kind, _))|
489+
// exclude mutable statics
490+
if Some(kind) == mut_static_kind { None } else { Some(id) } )
496491
.collect();
497492
let n = leaks.len();
498493
self.dump_allocs(leaks);
@@ -609,7 +604,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
609604

610605
/// The alloc_id must refer to a (mutable) static; a deep copy of that
611606
/// static is made into this memory.
612-
pub fn deep_copy_static(
607+
fn deep_copy_static(
613608
&mut self,
614609
id: AllocId,
615610
kind: MemoryKind<M::MemoryKinds>,
@@ -619,7 +614,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'a, 'mir, 'tcx, M> {
619614
return err!(ModifiedConstantMemory);
620615
}
621616
let old = self.alloc_map.insert(id, (kind, alloc.clone()));
622-
assert!(old.is_none(), "deep_copy_static: must not overwrite memory with");
617+
assert!(old.is_none(), "deep_copy_static: must not overwrite existing memory");
623618
Ok(())
624619
}
625620

src/librustc_mir/interpret/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
3131

3232
pub use self::memory::{Memory, MemoryKind};
3333

34-
pub use self::machine::{Machine, IsStatic};
34+
pub use self::machine::Machine;
3535

3636
pub use self::operand::{Value, ValTy, Operand, OpTy};
3737

src/librustc_mir/interpret/terminator.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
110110
}
111111
(instance, sig)
112112
}
113-
ref other => bug!("instance def ty: {:?}", other),
113+
_ => bug!("unexpected fn ptr to ty: {:?}", instance_ty),
114114
}
115115
}
116116
ty::FnDef(def_id, substs) => {

0 commit comments

Comments
 (0)