Skip to content

Commit 06486a1

Browse files
Merge pull request #836 from pnkfelix/1.52-fingerprinting
1.52.1 - Blog post explaining the fingerprint issue.
2 parents bd9d1c7 + 1dcc8be commit 06486a1

File tree

1 file changed

+235
-0
lines changed

1 file changed

+235
-0
lines changed

posts/2021-05-10-Rust-1.52.1.md

+235
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
---
2+
layout: post
3+
title: "Announcing Rust 1.52.1"
4+
author: Felix Klock, Mark Rousskov
5+
team: the compiler team <https://www.rust-lang.org/governance/teams/compiler>
6+
release: true
7+
---
8+
9+
The Rust team has prepared a new release, 1.52.1, working around a bug in
10+
incremental compilation which was made into a compiler error in 1.52.0. We
11+
recommend all Rust users, including those currently using stable versions prior
12+
to 1.52.0, upgrade to 1.52.1 or disable incremental compilation. Guidance on how
13+
to do so is available below.
14+
15+
If you have a previous version of Rust installed via rustup, getting Rust
16+
1.52.1 is as easy as:
17+
18+
```console
19+
rustup update stable
20+
```
21+
22+
If you don't have it already, you can [get `rustup`][install]
23+
from the appropriate page on our website.
24+
25+
[install]: https://www.rust-lang.org/install.html
26+
27+
# Summary
28+
29+
This release works around broken builds on 1.52.0, which are caused by newly
30+
added verification. The bugs this verification detects are present in all Rust
31+
versions[^1], and can trigger miscompilations in incremental builds, so downgrading
32+
to a prior stable version is not a fix.
33+
34+
Users are encouraged to upgrade to 1.52.1 or disable incremental in their local
35+
environment if on a prior version: please see the [what you should do][part3]
36+
section for details on how to do so.
37+
38+
Incremental compilation is off by default for release builds, so few
39+
production builds should be affected (only for users who have opted in).
40+
41+
Miscompilations that can arise from the bugs in incremental compilation generate incorrect code in final
42+
artifacts, essentially producing malformed binaries, which means that in theory
43+
any behavior is possible. In practice we are currently only aware of one
44+
particular known miscompilation, but bugs due to incremental are notoriously
45+
hard to track down: users frequently simply rebuild after some light editing if
46+
they see unexpected results from their binaries, and this often causes
47+
sufficient recompilation to fix the bug(s).
48+
49+
This post is going to:
50+
51+
1. Explain [what the errors look like][part0],
52+
1. Explain [what the check does][part1], at a high level,
53+
2. Explain [how the check is presenting itself][part2] in the Rust 1.52.0 release,
54+
3. Tell you [what you should do][part3] if you see an unstable fingerprint on your project,
55+
4. Describe our plans for [how the Rust project will address][part4] the problems discussed here.
56+
57+
[part0]: #what-does-the-error-look-like
58+
[part1]: #what-are-fingerprints-why-are-we-checking-them
59+
[part2]: #how-does-this-show-up
60+
[part3]: #what-should-a-rust-programmer-do-in-response
61+
[part4]: #what-is-the-rust-project-going-to-do-to-fix-this
62+
63+
## What does the error look like?
64+
65+
The error message looks something like this, with the key piece being the "found
66+
unstable fingerprints" text.
67+
68+
```text
69+
thread 'rustc' panicked at 'assertion failed: `(left == right)`
70+
left: `Some(Fingerprint(4565771098143344972, 7869445775526300234))`,
71+
right: `Some(Fingerprint(14934403843752251060, 623484215826468126))`: found unstable fingerprints for <massive text describing rustc internals elided>
72+
73+
error: internal compiler error: unexpected panic
74+
75+
note: the compiler unexpectedly panicked. this is a bug.
76+
```
77+
78+
This is the error caused by the internal consistency check, and as stated in the diagnostic, it yields an "Internal Compiler Error" (or ICE). In other words, it represents a bug in the internals of the Rust compiler itself. In *this* case, the ICE is revealing a bug in incremental compilation that predates the 1.52.0 release and could result in miscompilation if it had not been caught.
79+
80+
## What are fingerprints? Why are we checking them?
81+
82+
The Rust compiler has support for "incremental compilation", which has been described in a [2016 blog post][]. When incremental compilation is turned on, the compiler breaks the input source into pieces, and tracks how those input pieces influence the final build product. Then, when the inputs change, it detects this and reuses artifacts from previous builds, striving to expend effort solely on building the parts that need to respond to the changes to the input source code.
83+
84+
[2016 blog post]: https://blog.rust-lang.org/2016/09/08/incremental.html
85+
86+
Fingerprints are part of our architecture for detecting when inputs change. More specifically, a fingerprint (along with some other state to establish context) is a 128-bit value intended to uniquely identify internal values used within the compiler. Some compiler-internal results are stored on disk ("cached") between runs. Fingerprints are used to validate that a newly computed result is unchanged from the cached result. (More details about this are available in the [relevant chapter of the rustc dev guide][rustc-dev-guide-fingerprints].)
87+
88+
[rustc-dev-guide-fingerprints]: https://rustc-dev-guide.rust-lang.org/queries/incremental-compilation-in-detail.html#checking-query-results-for-changes-hashstable-and-fingerprints
89+
90+
The fingerprint stability check is a safeguard asserting internal consistency of
91+
the fingerprints. Sometimes the compiler is forced to rerun a query, and expects
92+
that the output is the same as from a prior incremental compilation session. The
93+
newly enabled verification checks that the value is indeed as expected, rather
94+
than assuming so. In some cases, due to bugs in the compiler's implementation,
95+
this was not actually the case.
96+
97+
## History
98+
99+
We [initially added][pr-45867] these fingerprint checks as a tool to use when
100+
developing rustc itself, back in 2017. It was solely provided via an unstable
101+
`-Z` flag, only available to nightly and development builds.
102+
103+
More recently, in March, we encountered a [miscompilation][issue-82920] that led us to [turn on `verify-ich` by default][pr-83007]. The Rust compiler team decided it was better to catch fingerprint problems and abort compilation, rather than allow for potential miscompilations (and subsequent misbehavior) to sneak into Rust programmer's binaries.
104+
105+
[pr-45867]: https://github.com/rust-lang/rust/pull/45867
106+
[issue-82920]: https://github.com/rust-lang/rust/issues/82920
107+
[pr-83007]: https://github.com/rust-lang/rust/pull/83007
108+
109+
When we first turned on the fingerprint checks by default, there was a steady
110+
stream of issues filed by users of the nightly (and beta) toolchains, and steady
111+
progress has been made on identifying fixes, a number of which have already
112+
landed.
113+
114+
In the past week, we had started [making plans][issue-84970] to improve the
115+
user-experience, so that the diagnostic issued by the check would do a better
116+
job of telling the programmer what to do in response. Unfortunately, this was
117+
done under the assumption that the new verification would ship in 1.53, not
118+
1.52.
119+
120+
[issue-84970]: https://github.com/rust-lang/rust/issues/84970
121+
122+
It turns out `verify-ich` was turned on in version 1.52.0, which was [released recently][].
123+
124+
[released recently]: /2021/05/06/Rust-1.52.0.html
125+
126+
Today's new release, 1.52.1, works around the breakage caused by the newly added
127+
verification by temporarily changing the defaults in the Rust compiler to disable
128+
incremental unless the user knowingly opts in.
129+
130+
## How does this show up
131+
132+
Essentially, for some crates, certain sequences of edit-compile cycles will cause `rustc` to hit the "unstable fingerprints" ICE. I showed one example at the start of this blog post.
133+
134+
Another recent example looks [like this](https://github.com/rust-lang/rust/issues/85039):
135+
136+
```text
137+
thread 'rustc' panicked at 'found unstable fingerprints for predicates_of(<massive text describing rustc internals elided>)', /rustc/.../compiler/rustc_query_system/src/query/plumbing.rs:593:5
138+
```
139+
140+
They all arise from inconsistencies when comparing the incremental-compilation cache stored on disk against the values computed during a current `rustc` invocation, which means they all arise from using incremental compilation.
141+
142+
There are several ways that you may have incremental compilation turned on:
143+
144+
1. You may be building with the `dev` or `test` [profiles][] which default to having incremental compilation enabled.
145+
2. You may have set the [environment variable][env-vars] `CARGO_INCREMENTAL=1`
146+
3. You may have enabled the `build.incremental` [setting in your Cargo config][cargo-config]
147+
4. You may have enabled the `incremental` [setting in your Cargo.toml][cargo-toml] for a given profile
148+
149+
[env-vars]: https://doc.rust-lang.org/cargo/reference/environment-variables.html#environment-variables-cargo-reads
150+
[cargo-config]: https://doc.rust-lang.org/cargo/reference/config.html#buildincremental
151+
[cargo-toml]: https://doc.rust-lang.org/cargo/reference/profiles.html#incremental
152+
[profiles]: https://doc.rust-lang.org/cargo/reference/profiles.html
153+
154+
If your project has not adjusted the defaults, then when running `cargo build
155+
--release` or otherwise in the `release` profile configuration incremental is
156+
disabled on all Rust versions[^1], and these issues should not affect your release
157+
builds.
158+
159+
## What should a Rust programmer do in response
160+
161+
The Internal Compiler Error asks you to report a bug, and if you can do so, we still want that information. We *want* to know about the cases that are failing.
162+
163+
But regardless of whether or not you file a bug, the problem can be worked around on your end by either:
164+
165+
1. upgrading to 1.52.1, if you have not yet done so (which will disable
166+
incremental for you), or
167+
2. deleting your incremental compilation cache (e.g. by running `cargo clean`), or
168+
3. forcing incremental compilation to be disabled, by setting `CARGO_INCREMENTAL=0` in your environment or `build.incremental` to `false` in the `config.toml`.
169+
170+
We recommend that users of 1.52.0 upgrade to 1.52.1, which disables incremental
171+
compilation.
172+
173+
We do *not* recommend that users of 1.52.0 downgrade to an earlier version of Rust in response to this problem. As noted above, there is at least one instance of a silent [miscompilation][issue-82920] caused by incremental compilation that was not caught until we added the fingerprint checking.
174+
175+
If a user is willing to deal with the incremental verification ICE's, and wishes
176+
to opt back into the 1.52.0 behavior, they may set `RUSTC_FORCE_INCREMENTAL` to
177+
`1` in their environment. The Rust compiler will then respect the
178+
`-Cincremental` option passed by Cargo, and things will work as before, though
179+
with the added verification. Note that this flag does not enable incremental if
180+
it has not already been separately enabled (whether by Cargo or otherwise).
181+
182+
If you are currently using a toolchain prior to 1.52.0, and wish to continue
183+
doing so, we recommend that you disable incremental compilation to avoid hitting
184+
silent miscompilations.
185+
186+
On all Rust builds since incremental has landed, it has been a major
187+
improvement to compile times for many users, and has only improved over time. We
188+
acknowledge that the workarounds presented here and recommendations are painful,
189+
and will be working hard to ensure the situation is as temporary as possible.
190+
191+
## What is the Rust project going to do to fix this
192+
193+
### Short-term plan
194+
195+
We have issued 1.52.1 today which:
196+
197+
* Disables incremental compilation in the Rust compiler (unless asked for by a
198+
new environment variable, `RUSTC_FORCE_INCREMENTAL=1`).
199+
* Improves diagnostic output for the new verification if incremental compilation is enabled,
200+
indicating how to work around the bugs by purging incremental state or
201+
disabling incremental.
202+
203+
This is intended to be a mitigation that helps the majority of Rust users have
204+
an upgrade path to a safe Rust compiler which does not have the risk of
205+
miscompiling their code, but also provide the option for users willing to deal
206+
with the errors to do so.
207+
208+
We expect to continue to actively invest in fixing the bugs, and depending on
209+
our confidence in the fixes, may issue a 1.52.2 point release which backports
210+
those fixes to the stable channel. Users wishing to help us test can use the
211+
nightly channel, and report bugs to rust-lang/rust with any ICEs they
212+
are seeing.
213+
214+
We are also currently not planning to disable incremental on the beta channel,
215+
but this decision has not been firmly committed to. A number of fixes are
216+
available on 1.53 beta today, so users who wish to continue using incremental
217+
may want to switch to that. Nightly will always have the latest in fixes, of
218+
course.
219+
220+
### Long-term plan
221+
222+
The long-term plan is to fix the bugs! Incremental compilation is the only realistic way for the Rust compiler to be able to provide a fast edit-compile-run cycle for all of its programmers, and so we need to address [all of the issues][issue-list] that have been identified thus far via `verify-ich`. (There are 32 such issues as of this writing, though many are duplicates.)
223+
224+
We are actively investing in this, and a number of bugs have already been
225+
identified and fixed. Depending on the state of the fixes, future stable
226+
releases (1.53 and onwards) will likely re-enable incremental compilation.
227+
228+
[issue-list]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+unstable+fingerprints
229+
230+
The Rust teams will also be developing plans to ensure we have better tracking
231+
systems in place in the future for bugs, both to prevent situations like this
232+
from arising again, but also to further increase the stability of our releases
233+
by tracking bugs more accurately as they propagate across channels.
234+
235+
[^1]: Since incremental was first enabled, which was in Rust 1.24.

0 commit comments

Comments
 (0)