diff options
| author | Oliver Schneider <git-no-reply-9879165716479413131@oli-obk.de> | 2017-07-13 17:25:17 +0200 |
|---|---|---|
| committer | Oliver Schneider <git-no-reply-9879165716479413131@oli-obk.de> | 2017-07-14 17:39:19 +0200 |
| commit | eb01c3fdd2ee6141f5e6a43d60f8a095e2c807f4 (patch) | |
| tree | 3d47e53b2ff6c7a0973463d2e63a1c85e852925f /src | |
| parent | 70a914cd34432b49da06c9778fceebd638bfa91d (diff) | |
| download | rust-eb01c3fdd2ee6141f5e6a43d60f8a095e2c807f4.tar.gz rust-eb01c3fdd2ee6141f5e6a43d60f8a095e2c807f4.zip | |
Use enum instead of boolean
Diffstat (limited to 'src')
| -rw-r--r-- | src/const_eval.rs | 8 | ||||
| -rw-r--r-- | src/eval_context.rs | 27 | ||||
| -rw-r--r-- | src/lvalue.rs | 9 | ||||
| -rw-r--r-- | src/memory.rs | 41 | ||||
| -rw-r--r-- | src/step.rs | 23 | ||||
| -rw-r--r-- | src/traits.rs | 4 |
6 files changed, 61 insertions, 51 deletions
diff --git a/src/const_eval.rs b/src/const_eval.rs index 771b740b375..b538d2d8357 100644 --- a/src/const_eval.rs +++ b/src/const_eval.rs @@ -1,5 +1,6 @@ use rustc::traits::Reveal; use rustc::ty::{self, TyCtxt, Ty, Instance}; +use syntax::ast::Mutability; use error::{EvalError, EvalResult}; use lvalue::{Global, GlobalId, Lvalue}; @@ -25,7 +26,12 @@ pub fn eval_body_as_primval<'a, 'tcx>( ecx.tcx, ty::ParamEnv::empty(Reveal::All), mir.span); - let cleanup = StackPopCleanup::MarkStatic(mutable); + let mutability = if mutable { + Mutability::Mutable + } else { + Mutability::Immutable + }; + let cleanup = StackPopCleanup::MarkStatic(mutability); let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id())); trace!("pushing stack frame for global: {}", name); ecx.push_stack_frame( diff --git a/src/eval_context.rs b/src/eval_context.rs index ac39cc4339d..76ed797684b 100644 --- a/src/eval_context.rs +++ b/src/eval_context.rs @@ -12,7 +12,7 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, Binder}; use rustc::traits; use rustc_data_structures::indexed_vec::Idx; use syntax::codemap::{self, DUMMY_SP, Span}; -use syntax::ast; +use syntax::ast::{self, Mutability}; use syntax::abi::Abi; use error::{EvalError, EvalResult}; @@ -98,8 +98,7 @@ pub enum StackPopCleanup { /// isn't modifyable afterwards in case of constants. /// In case of `static mut`, mark the memory to ensure it's never marked as immutable through /// references or deallocated - /// The bool decides whether the value is mutable (true) or not (false) - MarkStatic(bool), + MarkStatic(Mutability), /// A regular stackframe added due to a function call will need to get forwarded to the next /// block Goto(mir::BasicBlock), @@ -354,23 +353,23 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { // FIXME: to_ptr()? might be too extreme here, static zsts might reach this under certain conditions Value::ByRef(ptr, _aligned) => // Alignment does not matter for this call - self.memory.mark_static_initalized(ptr.to_ptr()?.alloc_id, !mutable)?, + self.memory.mark_static_initalized(ptr.to_ptr()?.alloc_id, mutable)?, Value::ByVal(val) => if let PrimVal::Ptr(ptr) = val { - self.memory.mark_inner_allocation(ptr.alloc_id, !mutable)?; + self.memory.mark_inner_allocation(ptr.alloc_id, mutable)?; }, Value::ByValPair(val1, val2) => { if let PrimVal::Ptr(ptr) = val1 { - self.memory.mark_inner_allocation(ptr.alloc_id, !mutable)?; + self.memory.mark_inner_allocation(ptr.alloc_id, mutable)?; } if let PrimVal::Ptr(ptr) = val2 { - self.memory.mark_inner_allocation(ptr.alloc_id, !mutable)?; + self.memory.mark_inner_allocation(ptr.alloc_id, mutable)?; } }, } // see comment on `initialized` field assert!(!global_value.initialized); global_value.initialized = true; - assert!(global_value.mutable); + assert_eq!(global_value.mutable, Mutability::Mutable); global_value.mutable = mutable; } else { bug!("StackPopCleanup::MarkStatic on: {:?}", frame.return_lvalue); @@ -1023,7 +1022,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } Lvalue::Ptr { .. } => lvalue, Lvalue::Global(cid) => { - let global_val = *self.globals.get(&cid).expect("global not cached"); + let global_val = self.globals.get(&cid).expect("global not cached").clone(); match global_val.value { Value::ByRef(ptr, aligned) => Lvalue::Ptr { ptr, aligned, extra: LvalueExtra::None }, @@ -1033,7 +1032,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { self.write_value_to_ptr(global_val.value, ptr.into(), global_val.ty)?; // see comment on `initialized` field if global_val.initialized { - self.memory.mark_static_initalized(ptr.alloc_id, !global_val.mutable)?; + self.memory.mark_static_initalized(ptr.alloc_id, global_val.mutable)?; } let lval = self.globals.get_mut(&cid).expect("already checked"); *lval = Global { @@ -1109,8 +1108,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { match dest { Lvalue::Global(cid) => { - let dest = *self.globals.get_mut(&cid).expect("global should be cached"); - if !dest.mutable { + let dest = self.globals.get_mut(&cid).expect("global should be cached").clone(); + if dest.mutable == Mutability::Immutable { return Err(EvalError::ModifiedConstantMemory); } let write_dest = |this: &mut Self, val| { @@ -1595,8 +1594,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { pub fn modify_global<F>(&mut self, cid: GlobalId<'tcx>, f: F) -> EvalResult<'tcx> where F: FnOnce(&mut Self, Value) -> EvalResult<'tcx, Value>, { - let mut val = *self.globals.get(&cid).expect("global not cached"); - if !val.mutable { + let mut val = self.globals.get(&cid).expect("global not cached").clone(); + if val.mutable == Mutability::Immutable { return Err(EvalError::ModifiedConstantMemory); } val.value = f(self, val.value)?; diff --git a/src/lvalue.rs b/src/lvalue.rs index f4a1f050735..5e02bb4a572 100644 --- a/src/lvalue.rs +++ b/src/lvalue.rs @@ -2,6 +2,7 @@ use rustc::mir; use rustc::ty::layout::{Size, Align}; use rustc::ty::{self, Ty}; use rustc_data_structures::indexed_vec::Idx; +use syntax::ast::Mutability; use error::{EvalError, EvalResult}; use eval_context::EvalContext; @@ -51,7 +52,7 @@ pub struct GlobalId<'tcx> { pub(super) promoted: Option<mir::Promoted>, } -#[derive(Copy, Clone, Debug)] +#[derive(Clone, Debug)] pub struct Global<'tcx> { pub(super) value: Value, /// Only used in `force_allocation` to ensure we don't mark the memory @@ -59,7 +60,7 @@ pub struct Global<'tcx> { /// global which initially is `Value::ByVal(PrimVal::Undef)` and gets /// lifted to an allocation before the static is fully initialized pub(super) initialized: bool, - pub(super) mutable: bool, + pub(super) mutable: Mutability, pub(super) ty: Ty<'tcx>, } @@ -113,13 +114,13 @@ impl<'tcx> Global<'tcx> { pub(super) fn uninitialized(ty: Ty<'tcx>) -> Self { Global { value: Value::ByVal(PrimVal::Undef), - mutable: true, + mutable: Mutability::Mutable, ty, initialized: false, } } - pub(super) fn initialized(ty: Ty<'tcx>, value: Value, mutable: bool) -> Self { + pub(super) fn initialized(ty: Ty<'tcx>, value: Value, mutable: Mutability) -> Self { Global { value, mutable, diff --git a/src/memory.rs b/src/memory.rs index b25d69e5d07..75ebff2f97b 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -4,6 +4,7 @@ use std::{fmt, iter, ptr, mem, io}; use rustc::ty; use rustc::ty::layout::{self, TargetDataLayout}; +use syntax::ast::Mutability; use error::{EvalError, EvalResult}; use value::{PrimVal, self, Pointer}; @@ -35,7 +36,7 @@ pub struct Allocation { /// The alignment of the allocation to detect unaligned reads. pub align: u64, /// Whether the allocation may be modified. - pub mutable: bool, + pub mutable: Mutability, /// Use the `mark_static_initalized` method of `Memory` to ensure that an error occurs, if the memory of this /// allocation is modified or deallocated in the future. /// Helps guarantee that stack allocations aren't deallocated via `rust_deallocate` @@ -50,6 +51,11 @@ pub enum Kind { C, /// Error if deallocated except during a stack pop Stack, + /// Static in the process of being initialized. + /// The difference is important: An immutable static referring to a + /// mutable initialized static will freeze immutably and would not + /// be able to distinguish already initialized statics from uninitialized ones + UninitializedStatic, /// May never be deallocated Static, /// Part of env var emulation @@ -189,7 +195,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { let ptr = self.allocate(bytes.len() as u64, 1, Kind::Static)?; self.write_bytes(PrimVal::Ptr(ptr), bytes)?; - self.mark_static_initalized(ptr.alloc_id, true)?; + self.mark_static_initalized(ptr.alloc_id, Mutability::Mutable)?; self.literal_alloc_cache.insert(bytes.to_vec(), ptr.alloc_id); Ok(ptr) } @@ -213,7 +219,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { undef_mask: UndefMask::new(size), align, kind, - mutable: true, + mutable: Mutability::Mutable, }; let id = self.next_id; self.next_id.0 += 1; @@ -404,7 +410,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { pub fn get_mut(&mut self, id: AllocId) -> EvalResult<'tcx, &mut Allocation> { match self.alloc_map.get_mut(&id) { - Some(alloc) => if alloc.mutable { + Some(alloc) => if alloc.mutable == Mutability::Mutable { Ok(alloc) } else { Err(EvalError::ModifiedConstantMemory) @@ -477,8 +483,9 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } let immutable = match (alloc.kind, alloc.mutable) { - (Kind::Static, true) => " (static mut)", - (Kind::Static, false) => " (immutable)", + (Kind::UninitializedStatic, _) => " (static in the process of initialization)", + (Kind::Static, Mutability::Mutable) => " (static mut)", + (Kind::Static, Mutability::Immutable) => " (immutable)", (Kind::Env, _) => " (env var)", (Kind::C, _) => " (malloc)", (Kind::Rust, _) => " (heap)", @@ -584,31 +591,23 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { } /// mark an allocation pointed to by a static as static and initialized - pub fn mark_inner_allocation(&mut self, alloc: AllocId, make_immutable: bool) -> EvalResult<'tcx> { + pub fn mark_inner_allocation(&mut self, alloc: AllocId, mutability: Mutability) -> EvalResult<'tcx> { // relocations into other statics are not "inner allocations" if !self.static_alloc.contains(&alloc) { - self.mark_static_initalized(alloc, make_immutable)?; + self.mark_static_initalized(alloc, mutability)?; } Ok(()) } /// mark an allocation as static and initialized, either mutable or not - pub fn mark_static_initalized(&mut self, alloc_id: AllocId, make_immutable: bool) -> EvalResult<'tcx> { - trace!("mark_static_initalized {:?}, make_immutable: {:?}", alloc_id, make_immutable); + pub fn mark_static_initalized(&mut self, alloc_id: AllocId, mutability: Mutability) -> EvalResult<'tcx> { + trace!("mark_static_initalized {:?}, mutability: {:?}", alloc_id, mutability); // do not use `self.get_mut(alloc_id)` here, because we might have already marked a // sub-element or have circular pointers (e.g. `Rc`-cycles) let relocations = match self.alloc_map.get_mut(&alloc_id) { - Some(&mut Allocation { kind: Kind::Static, ref mut mutable, .. }) => { - if make_immutable { - *mutable = false; - } - return Ok(()); - }, - Some(&mut Allocation { ref mut relocations, ref mut kind, ref mut mutable, .. }) => { + Some(&mut Allocation { ref mut relocations, kind: ref mut kind @ Kind::UninitializedStatic, ref mut mutable, .. }) => { *kind = Kind::Static; - if make_immutable { - *mutable = false; - } + *mutable = mutability; // take out the relocations vector to free the borrow on self, so we can call // mark recursively mem::replace(relocations, Default::default()) @@ -618,7 +617,7 @@ impl<'a, 'tcx> Memory<'a, 'tcx> { }; // recurse into inner allocations for &alloc in relocations.values() { - self.mark_inner_allocation(alloc, make_immutable)?; + self.mark_inner_allocation(alloc, mutability)?; } // put back the relocations self.alloc_map.get_mut(&alloc_id).expect("checked above").relocations = relocations; diff --git a/src/step.rs b/src/step.rs index 3aafda47636..d854218d7a9 100644 --- a/src/step.rs +++ b/src/step.rs @@ -15,6 +15,7 @@ use eval_context::{EvalContext, StackPopCleanup}; use lvalue::{Global, GlobalId, Lvalue}; use value::{Value, PrimVal}; use syntax::codemap::Span; +use syntax::ast::Mutability; impl<'a, 'tcx> EvalContext<'a, 'tcx> { pub fn inc_step_counter_and_check_limit(&mut self, n: u64) -> EvalResult<'tcx> { @@ -162,7 +163,7 @@ impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> { def_id: DefId, substs: &'tcx subst::Substs<'tcx>, span: Span, - shared: bool, + mutability: Mutability, ) { let instance = self.ecx.resolve_associated_const(def_id, substs); let cid = GlobalId { instance, promoted: None }; @@ -171,18 +172,22 @@ impl<'a, 'b, 'tcx> ConstantExtractor<'a, 'b, 'tcx> { } if self.ecx.tcx.has_attr(def_id, "linkage") { trace!("Initializing an extern global with NULL"); - self.ecx.globals.insert(cid, Global::initialized(self.ecx.tcx.type_of(def_id), Value::ByVal(PrimVal::Bytes(0)), !shared)); + self.ecx.globals.insert(cid, Global::initialized(self.ecx.tcx.type_of(def_id), Value::ByVal(PrimVal::Bytes(0)), mutability)); return; } self.try(|this| { let mir = this.ecx.load_mir(instance.def)?; this.ecx.globals.insert(cid, Global::uninitialized(mir.return_ty)); - let mutable = !shared || - !mir.return_ty.is_freeze( + let internally_mutable = !mir.return_ty.is_freeze( this.ecx.tcx, ty::ParamEnv::empty(Reveal::All), span); - let cleanup = StackPopCleanup::MarkStatic(mutable); + let mutability = if mutability == Mutability::Mutable || internally_mutable { + Mutability::Mutable + } else { + Mutability::Immutable + }; + let cleanup = StackPopCleanup::MarkStatic(mutability); let name = ty::tls::with(|tcx| tcx.item_path_str(def_id)); trace!("pushing stack frame for global: {}", name); this.ecx.push_stack_frame( @@ -214,7 +219,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> { // already computed by rustc mir::Literal::Value { .. } => {} mir::Literal::Item { def_id, substs } => { - self.global_item(def_id, substs, constant.span, true); + self.global_item(def_id, substs, constant.span, Mutability::Immutable); }, mir::Literal::Promoted { index } => { let cid = GlobalId { @@ -233,7 +238,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> { constant.span, mir, Lvalue::Global(cid), - StackPopCleanup::MarkStatic(false), + StackPopCleanup::MarkStatic(Mutability::Immutable), ) }); } @@ -254,7 +259,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> { if let Some(node_item) = self.ecx.tcx.hir.get_if_local(def_id) { if let hir::map::Node::NodeItem(&hir::Item { ref node, .. }) = node_item { if let hir::ItemStatic(_, m, _) = *node { - self.global_item(def_id, substs, span, m == hir::MutImmutable); + self.global_item(def_id, substs, span, if m == hir::MutMutable { Mutability::Mutable } else { Mutability::Immutable }); return; } else { bug!("static def id doesn't point to static"); @@ -265,7 +270,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for ConstantExtractor<'a, 'b, 'tcx> { } else { let def = self.ecx.tcx.describe_def(def_id).expect("static not found"); if let hir::def::Def::Static(_, mutable) = def { - self.global_item(def_id, substs, span, !mutable); + self.global_item(def_id, substs, span, if mutable { Mutability::Mutable } else { Mutability::Immutable }); } else { bug!("static found but isn't a static: {:?}", def); } diff --git a/src/traits.rs b/src/traits.rs index 6fbb973d7b1..b3e77a9299c 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -8,7 +8,7 @@ use rustc::hir::def_id::DefId; use rustc::ty::subst::Substs; use rustc::ty::{self, Ty}; use syntax::codemap::DUMMY_SP; -use syntax::ast; +use syntax::ast::{self, Mutability}; use error::{EvalResult, EvalError}; @@ -68,7 +68,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { } } - self.memory.mark_static_initalized(vtable.alloc_id, true)?; + self.memory.mark_static_initalized(vtable.alloc_id, Mutability::Mutable)?; Ok(vtable) } |
