]> git.lizzy.rs Git - rust.git/blob - src/locks.rs
rustup for big refactor; kill most of validation
[rust.git] / src / locks.rs
1 #![allow(unused)]
2
3 use super::*;
4 use rustc::middle::region;
5 use rustc::ty::layout::Size;
6
7 ////////////////////////////////////////////////////////////////////////////////
8 // Locks
9 ////////////////////////////////////////////////////////////////////////////////
10
11 // Just some dummy to keep this compiling; I think some of this will be useful later
12 type AbsPlace<'tcx> = ::rustc::ty::Ty<'tcx>;
13
14 /// Information about a lock that is currently held.
15 #[derive(Clone, Debug, PartialEq, Eq)]
16 pub struct LockInfo<'tcx> {
17     /// Stores for which lifetimes (of the original write lock) we got
18     /// which suspensions.
19     suspended: HashMap<WriteLockId<'tcx>, Vec<region::Scope>>,
20     /// The current state of the lock that's actually effective.
21     pub active: Lock,
22 }
23
24 /// Write locks are identified by a stack frame and an "abstract" (untyped) place.
25 /// It may be tempting to use the lifetime as identifier, but that does not work
26 /// for two reasons:
27 /// * First of all, due to subtyping, the same lock may be referred to with different
28 ///   lifetimes.
29 /// * Secondly, different write locks may actually have the same lifetime.  See `test2`
30 ///   in `run-pass/many_shr_bor.rs`.
31 /// The Id is "captured" when the lock is first suspended; at that point, the borrow checker
32 /// considers the path frozen and hence the Id remains stable.
33 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
34 pub struct WriteLockId<'tcx> {
35     frame: usize,
36     path: AbsPlace<'tcx>,
37 }
38
39
40 use rustc::mir::interpret::Lock::*;
41 use rustc::mir::interpret::Lock;
42
43 impl<'tcx> Default for LockInfo<'tcx> {
44     fn default() -> Self {
45         LockInfo::new(NoLock)
46     }
47 }
48
49 impl<'tcx> LockInfo<'tcx> {
50     fn new(lock: Lock) -> LockInfo<'tcx> {
51         LockInfo {
52             suspended: HashMap::new(),
53             active: lock,
54         }
55     }
56
57     fn access_permitted(&self, frame: Option<usize>, access: AccessKind) -> bool {
58         use super::AccessKind::*;
59         match (&self.active, access) {
60             (&NoLock, _) => true,
61             (&ReadLock(ref lfts), Read) => {
62                 assert!(!lfts.is_empty(), "Someone left an empty read lock behind.");
63                 // Read access to read-locked region is okay, no matter who's holding the read lock.
64                 true
65             }
66             (&WriteLock(ref lft), _) => {
67                 // All access is okay if we are the ones holding it
68                 Some(lft.frame) == frame
69             }
70             _ => false, // Nothing else is okay.
71         }
72     }
73 }
74
75 impl<'tcx> RangeMap<LockInfo<'tcx>> {
76     pub fn check(
77         &self,
78         frame: Option<usize>,
79         offset: u64,
80         len: u64,
81         access: AccessKind,
82     ) -> Result<(), LockInfo<'tcx>> {
83         if len == 0 {
84             return Ok(());
85         }
86         for lock in self.iter(offset, len) {
87             // Check if the lock is in conflict with the access.
88             if !lock.access_permitted(frame, access) {
89                 return Err(lock.clone());
90             }
91         }
92         Ok(())
93     }
94 }