about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorOliver Schneider <git-no-reply-9879165716479413131@oli-obk.de>2017-07-13 17:25:17 +0200
committerOliver Schneider <git-no-reply-9879165716479413131@oli-obk.de>2017-07-14 17:39:19 +0200
commiteb01c3fdd2ee6141f5e6a43d60f8a095e2c807f4 (patch)
tree3d47e53b2ff6c7a0973463d2e63a1c85e852925f /src
parent70a914cd34432b49da06c9778fceebd638bfa91d (diff)
downloadrust-eb01c3fdd2ee6141f5e6a43d60f8a095e2c807f4.tar.gz
rust-eb01c3fdd2ee6141f5e6a43d60f8a095e2c807f4.zip
Use enum instead of boolean
Diffstat (limited to 'src')
-rw-r--r--src/const_eval.rs8
-rw-r--r--src/eval_context.rs27
-rw-r--r--src/lvalue.rs9
-rw-r--r--src/memory.rs41
-rw-r--r--src/step.rs23
-rw-r--r--src/traits.rs4
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)
     }