ignore reads of tracked state when there is no current task

I realized that, even in the current system, such reads can't really do
any harm. Because they are not part of a task, they will occur no matter
what (only tasks can be skipped). If you leak the data you read into a
task, that is bad, but that is equally bad if you are in a task.

*Writes* to tracked state, on the other hand, should never occur except
from within a task (and the task then records what things you read to
compute it).

Once we complete the shift to on-demand, these properties will hold by
construction (because the on-demand struct enforces stateless tasks
where leaks are impossible -- except by having shared mutable state in
the tcx).
This commit is contained in:
Niko Matsakis 2017-03-23 16:45:21 -04:00
parent a3a5ff98eb
commit 69c9d9b3b8
2 changed files with 16 additions and 6 deletions

View File

@ -101,11 +101,15 @@ pub fn pop_task(&mut self, key: DepNode<D>) {
}
/// Indicates that the current task `C` reads `v` by adding an
/// edge from `v` to `C`. If there is no current task, panics. If
/// you want to suppress this edge, use `ignore`.
/// edge from `v` to `C`. If there is no current task, has no
/// effect. Note that *reading* from tracked state is harmless if
/// you are not in a task; what is bad is *writing* to tracked
/// state (and leaking data that you read into a tracked task).
pub fn read(&mut self, v: DepNode<D>) {
let source = self.make_node(v);
self.add_edge_from_current_node(|current| (source, current))
if self.current_node().is_some() {
let source = self.make_node(v);
self.add_edge_from_current_node(|current| (source, current))
}
}
/// Indicates that the current task `C` writes `v` by adding an

View File

@ -80,7 +80,13 @@ pub fn enqueue(&self, message: &DepMessage) {
let mut stack = self.stack.borrow_mut();
match *message {
DepMessage::Read(ref n) => self.check_edge(Some(Some(n)), top(&stack)),
// It is ok to READ shared state outside of a
// task. That can't do any harm (at least, the only
// way it can do harm is by leaking that data into a
// query or task, which would be a problem
// anyway). What would be bad is WRITING to that
// state.
DepMessage::Read(_) => { }
DepMessage::Write(ref n) => self.check_edge(top(&stack), Some(Some(n))),
DepMessage::PushTask(ref n) => stack.push(Some(n.clone())),
DepMessage::PushIgnore => stack.push(None),
@ -116,7 +122,7 @@ fn check_edge(&self,
(None, None) => unreachable!(),
// nothing on top of the stack
(None, Some(n)) | (Some(n), None) => bug!("read/write of {:?} but no current task", n),
(None, Some(n)) | (Some(n), None) => bug!("write of {:?} but no current task", n),
// this corresponds to an Ignore being top of the stack
(Some(None), _) | (_, Some(None)) => (),