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
//! Which lints are registered is an input to compilation that rustc's incremental dependency graph
//! knows nothing about. Writing the variables in [`UNTRACKED_STATE_VARS`] to `sess.env_depinfo`
//! (see `Callbacks::config`) tells Cargo to re-invoke rustc when the input changes, but it does not
//! tell rustc to distrust its cache: `env_depinfo` is written to the dep-info file for the build
//! system to read, and nothing in rustc reads it back. So rustc reloads a cache produced with a
//! different set of registered lints, sees that everything it recorded as an input to its dep-graph
//! nodes is unchanged (it marks them "green"), and ICEs when a query such as
//! `shallow_lint_levels_on` recomputes to a different value anyway. See
//! <https://github.com/trailofbits/dylint/issues/2010>.
//!
//! rustc discards its cache when `Options::dep_tracking_hash` changes, so the fix is to get the
//! state into that hash. `rustc_interface::Config::track_state` looks like the way to do that, but
//! its hasher was removed in <https://github.com/rust-lang/rust/pull/155671>. What remains of the
//! callback can only write to `env_depinfo` and `file_depinfo`, which is the tracking that is
//! already insufficient.
//!
//! `--env-set` reaches the hash instead. Each field of `Options` is declared with a marker saying
//! whether it participates in `dep_tracking_hash`: `[UNTRACKED]` fields do not, `[TRACKED]` fields
//! do and also contribute to the crate hash, and `[TRACKED_NO_CRATE_HASH]` fields do only the
//! former. `--env-set` writes to `logical_env`, which is `[TRACKED]`, so changing its value still
//! causes rustc to discard its cache:
//! <https://github.com/rust-lang/rust/blob/78e7c7b9f9f6a671255ff0fb88b5a6fd6dbc7a58/compiler/rustc_session/src/options.rs#L106-L129>
use ;
use env;
use ;
/// The environment variable that carries the hash into `logical_env`.
///
/// Nothing reads the value back. It is set only so that changing it changes `dep_tracking_hash`.
pub const UNTRACKED_STATE_VAR: &str = "DYLINT_UNTRACKED_STATE";
/// The environment variables whose change should cause lints to be rerun.
///
/// `CARGO_PRIMARY_PACKAGE` and `DYLINT_NO_DEPS` determine whether lints are registered at all,
/// `DYLINT_LIBS` names the libraries that register them, and `DYLINT_METADATA` is the metadata from
/// which those libraries are resolved.
///
/// Read by two consumers that must not drift apart: `sess.env_depinfo`, which tells Cargo when to
/// re-invoke rustc, and [`hash_from_env`], which tells rustc when to discard its incremental cache.
/// A rerun needs both, since re-invoking rustc accomplishes nothing if rustc then reuses results
/// computed under the old values.
pub const UNTRACKED_STATE_VARS: & = &;
/// Reads [`UNTRACKED_STATE_VARS`] from the environment and forwards them to [`hash`].
pub
/// Hashes the state whose change should cause lints to be rerun.
///
/// `vars` are the values of [`UNTRACKED_STATE_VARS`]. They are passed in rather than read from the
/// environment so that this function is a function of its arguments alone.
///
/// Returns `None` if no libraries are loaded, in which case Dylint registers no lints and there is
/// no untracked state to account for.
pub