1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
pub mod debug;
pub mod dep_node;
mod edges;
mod graph;
mod query;
mod serialized;

pub use dep_node::{DepKind, DepKindStruct, DepNode, DepNodeParams, WorkProductId};
pub(crate) use graph::DepGraphData;
pub use graph::{hash_result, DepGraph, DepNodeIndex, TaskDepsRef, WorkProduct, WorkProductMap};
pub use query::DepGraphQuery;
pub use serialized::{SerializedDepGraph, SerializedDepNodeIndex};

use crate::ich::StableHashingContext;
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_session::Session;

use std::panic;

use self::graph::{print_markframe_trace, MarkFrame};

pub trait DepContext: Copy {
    type Deps: Deps;

    /// Create a hashing context for hashing new results.
    fn with_stable_hashing_context<R>(self, f: impl FnOnce(StableHashingContext<'_>) -> R) -> R;

    /// Access the DepGraph.
    fn dep_graph(&self) -> &DepGraph<Self::Deps>;

    /// Access the profiler.
    fn profiler(&self) -> &SelfProfilerRef;

    /// Access the compiler session.
    fn sess(&self) -> &Session;

    fn dep_kind_info(&self, dep_node: DepKind) -> &DepKindStruct<Self>;

    #[inline(always)]
    fn fingerprint_style(self, kind: DepKind) -> FingerprintStyle {
        let data = self.dep_kind_info(kind);
        if data.is_anon {
            return FingerprintStyle::Opaque;
        }
        data.fingerprint_style
    }

    #[inline(always)]
    /// Return whether this kind always require evaluation.
    fn is_eval_always(self, kind: DepKind) -> bool {
        self.dep_kind_info(kind).is_eval_always
    }

    /// Try to force a dep node to execute and see if it's green.
    #[inline]
    #[instrument(skip(self, frame), level = "debug")]
    fn try_force_from_dep_node(self, dep_node: DepNode, frame: Option<&MarkFrame<'_>>) -> bool {
        let cb = self.dep_kind_info(dep_node.kind);
        if let Some(f) = cb.force_from_dep_node {
            if let Err(value) = panic::catch_unwind(panic::AssertUnwindSafe(|| {
                f(self, dep_node);
            })) {
                if !value.is::<rustc_errors::FatalErrorMarker>() {
                    print_markframe_trace(self.dep_graph(), frame);
                }
                panic::resume_unwind(value)
            }
            true
        } else {
            false
        }
    }

    /// Load data from the on-disk cache.
    fn try_load_from_on_disk_cache(self, dep_node: DepNode) {
        let cb = self.dep_kind_info(dep_node.kind);
        if let Some(f) = cb.try_load_from_on_disk_cache {
            f(self, dep_node)
        }
    }
}

pub trait Deps {
    /// Execute the operation with provided dependencies.
    fn with_deps<OP, R>(deps: TaskDepsRef<'_>, op: OP) -> R
    where
        OP: FnOnce() -> R;

    /// Access dependencies from current implicit context.
    fn read_deps<OP>(op: OP)
    where
        OP: for<'a> FnOnce(TaskDepsRef<'a>);

    /// We use this for most things when incr. comp. is turned off.
    const DEP_KIND_NULL: DepKind;

    /// We use this to create a forever-red node.
    const DEP_KIND_RED: DepKind;

    /// This is the highest value a `DepKind` can have. It's used during encoding to
    /// pack information into the unused bits.
    const DEP_KIND_MAX: u16;
}

pub trait HasDepContext: Copy {
    type Deps: self::Deps;
    type DepContext: self::DepContext<Deps = Self::Deps>;

    fn dep_context(&self) -> &Self::DepContext;
}

impl<T: DepContext> HasDepContext for T {
    type Deps = T::Deps;
    type DepContext = Self;

    fn dep_context(&self) -> &Self::DepContext {
        self
    }
}

impl<T: HasDepContext, Q: Copy> HasDepContext for (T, Q) {
    type Deps = T::Deps;
    type DepContext = T::DepContext;

    fn dep_context(&self) -> &Self::DepContext {
        self.0.dep_context()
    }
}

/// Describes the contents of the fingerprint generated by a given query.
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum FingerprintStyle {
    /// The fingerprint is actually a DefPathHash.
    DefPathHash,
    /// The fingerprint is actually a HirId.
    HirId,
    /// Query key was `()` or equivalent, so fingerprint is just zero.
    Unit,
    /// Some opaque hash.
    Opaque,
}

impl FingerprintStyle {
    #[inline]
    pub fn reconstructible(self) -> bool {
        match self {
            FingerprintStyle::DefPathHash | FingerprintStyle::Unit | FingerprintStyle::HirId => {
                true
            }
            FingerprintStyle::Opaque => false,
        }
    }
}