]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/mir/graph_cyclic_cache.rs
Move ty::print methods to Drop-based scope guards
[rust.git] / compiler / rustc_middle / src / mir / graph_cyclic_cache.rs
1 use rustc_data_structures::graph::{
2     self, DirectedGraph, WithNumNodes, WithStartNode, WithSuccessors,
3 };
4 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5 use rustc_data_structures::sync::OnceCell;
6 use rustc_serialize as serialize;
7
8 /// Helper type to cache the result of `graph::is_cyclic`.
9 #[derive(Clone, Debug)]
10 pub(super) struct GraphIsCyclicCache {
11     cache: OnceCell<bool>,
12 }
13
14 impl GraphIsCyclicCache {
15     #[inline]
16     pub(super) fn new() -> Self {
17         GraphIsCyclicCache { cache: OnceCell::new() }
18     }
19
20     pub(super) fn is_cyclic<G>(&self, graph: &G) -> bool
21     where
22         G: ?Sized + DirectedGraph + WithStartNode + WithSuccessors + WithNumNodes,
23     {
24         *self.cache.get_or_init(|| graph::is_cyclic(graph))
25     }
26
27     /// Invalidates the cache.
28     #[inline]
29     pub(super) fn invalidate(&mut self) {
30         // Invalidating the cache requires mutating the MIR, which in turn requires a unique
31         // reference (`&mut`) to the `mir::Body`. Because of this, we can assume that all
32         // callers of `invalidate` have a unique reference to the MIR and thus to the
33         // cache. This means we never need to do synchronization when `invalidate` is called,
34         // we can simply reinitialize the `OnceCell`.
35         self.cache = OnceCell::new();
36     }
37 }
38
39 impl<S: serialize::Encoder> serialize::Encodable<S> for GraphIsCyclicCache {
40     #[inline]
41     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
42         serialize::Encodable::encode(&(), s)
43     }
44 }
45
46 impl<D: serialize::Decoder> serialize::Decodable<D> for GraphIsCyclicCache {
47     #[inline]
48     fn decode(d: &mut D) -> Self {
49         let () = serialize::Decodable::decode(d);
50         Self::new()
51     }
52 }
53
54 impl<CTX> HashStable<CTX> for GraphIsCyclicCache {
55     #[inline]
56     fn hash_stable(&self, _: &mut CTX, _: &mut StableHasher) {
57         // do nothing
58     }
59 }
60
61 TrivialTypeFoldableAndLiftImpls! {
62     GraphIsCyclicCache,
63 }