Skip to content

Commit 8dc8dfe

Browse files
Merge pull request #24 from ehuss/tutorial
Add a tutorial.
2 parents a323b98 + 3888da3 commit 8dc8dfe

File tree

2 files changed

+158
-0
lines changed

2 files changed

+158
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
This tool bisects either Rust nightlies or CI artifacts.
44

5+
[**Tutorial**](TUTORIAL.md)
6+
57
## License
68

79
Licensed under either of

TUTORIAL.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# Bisecting Regressions
2+
3+
The [`cargo-bisect-rustc`] tool makes it super easy to find exactly when
4+
behavior has changed in rustc. It automatically downloads rustc artifacts and
5+
tests them against a project you provide until it finds the regression. To
6+
install:
7+
8+
```sh
9+
git clone https://github.com/rust-lang-nursery/cargo-bisect-rustc.git
10+
RUST_SRC_REPO=/path/to/rust cargo install --path=cargo-bisect-rustc
11+
```
12+
13+
The `RUST_SRC_REPO` should be a path to a git clone of the rust repo. If you
14+
don't specify it, it will look in the current directory for `rust.git` or
15+
check it out automatically if it's not there (only necessary if doing git hash
16+
bisections).
17+
18+
Create a cargo project that demonstrates the regression. Let's use
19+
[issue #53157] as an example:
20+
21+
```
22+
cargo new foo
23+
```
24+
25+
Edit `foo/src/main.rs` with the example from the issue:
26+
27+
```rust
28+
macro_rules! m {
29+
() => {{
30+
fn f(_: impl Sized) {}
31+
f
32+
}}
33+
}
34+
35+
fn main() {
36+
fn f() -> impl Sized {};
37+
m!()(f());
38+
}
39+
```
40+
41+
## Regressing to a nightly
42+
43+
Let's find the first nightly where this fails. First you need to determine a
44+
nightly release where the code works, and one where it doesn't. We can see
45+
from the issue that we know stable 1.28.0 was working, and that it no longer
46+
works as of nightly 2018-08-04. We're testing against nightlies, and stable
47+
1.28.0 branched off master 12 weeks prior to its release, and the regression
48+
could have been introduced to master during that time, so I'll just take a
49+
guess that nightly 2018-05-07 is OK. Don't worry if you guess wrong,
50+
`cargo-bisect-rustc` will tell you and you can just pick a larger date range.
51+
To find the exact nightly release where it stopped working:
52+
53+
```
54+
cargo-bisect-rustc --test-dir=foo --start=2018-05-07 --end=2018-08-04
55+
```
56+
57+
By default it will run `cargo build` in the project and check whether or not
58+
it fails. In just a few steps, we find that it stopped working on
59+
`nightly-2018-07-30`.
60+
61+
> *Note:* Consider using the `--preserve` flag to keep the downloaded
62+
> artifacts for future runs. They are stored in the normal location for your
63+
> toolchains in `RUSTUP_HOME`.
64+
65+
## Regressing to a PR
66+
67+
But wait, we can do better! As long as the regression wasn't too long ago, we
68+
can find the exact PR that caused the regression. Use git hashes from the
69+
rustc repo's log as the start/end parameters. They must be from bors on the
70+
master branch. Assuming you aren't reading this too far in the future, the
71+
following should work:
72+
73+
```
74+
cargo-bisect-rustc --test-dir=foo \
75+
--start=6323d9a45bdf0ac2a9319a6a558537e0a7e6abd1 \
76+
--end=866a713258915e6cbb212d135f751a6a8c9e1c0a
77+
```
78+
79+
This tells us that the regression started with
80+
70cac59031d5c33962a1f53cdca9359c0dcd1f9f and you can look at the git log to
81+
find the PR.
82+
83+
## Testing interactively
84+
85+
Pass/fail of `cargo build` may not be what you're after. Perhaps the issue is
86+
an error message changed, so both the "good" and "bad" version will fail to
87+
compile, just with a different message. Or maybe something used to fail, and
88+
now erroneously passes. You can use the interactive feature with the
89+
`--prompt` flag to visually inspect a build and tell `cargo-bisect-rustc`
90+
what's "good" and what's "bad". Let's use [issue #55036] as an example where
91+
an error message changed:
92+
93+
`foo/src/main.rs`:
94+
```rust
95+
struct Foo {
96+
bar: i32
97+
}
98+
99+
trait Baz {
100+
fn f(Foo { bar }: Foo) {}
101+
}
102+
```
103+
104+
This historically emitted a bad error, was updated to emit a nice error (E0642
105+
added in #53051), but then that nice error was lost somewhere (on the 2015
106+
edition). Let's find where it was lost! Grab the ranges between where it was
107+
added and where we know it fails:
108+
109+
```
110+
cargo-bisect-rustc --prompt --test-dir=foo \
111+
--start=ab93561b5fa54954159480ddc10bbb69f015e539 \
112+
--end=2c2e2c57dc2140cfb62a8abb9312b89f02c59f3c
113+
```
114+
115+
At each step, `cargo-bisect-rustc` will show the output and ask you:
116+
117+
```
118+
ab93561b5fa54954159480ddc10bbb69f015e539 finished with exit code Some(101).
119+
please select an action to take:
120+
> mark regressed
121+
mark baseline
122+
retry
123+
```
124+
125+
Choose `mark baseline` with the nice E0642 message, and `mark regressed` with
126+
the less-favorable token error. Fairly quickly we find it regressed in
127+
af50e3822c4ceda60445c4a2adbb3bfa480ebd39 which is a rollup merge. However,
128+
it's not too hard to look through the commits and find a likely culprit.
129+
130+
## Testing with a script
131+
132+
Using the `--script` option allows you to do something more fancy than just
133+
`cargo build`. Maybe you need to run cargo multiple times, or just call
134+
`rustc` directly, or you want to automatically grep through the output. The
135+
possibilities are endless! Just write a little shell script that exits 0 for
136+
the baseline, and exits nonzero for the regression. As an example, the
137+
previous interactive session can be hands-free automated with this script:
138+
139+
`foo/test.sh`:
140+
```sh
141+
#!/bin/sh
142+
cargo check 2>&1 | grep E0642
143+
```
144+
145+
And then run:
146+
147+
```
148+
cargo-bisect-rustc --script=./test.sh --test-dir=foo \
149+
--start=ab93561b5fa54954159480ddc10bbb69f015e539 \
150+
--end=2c2e2c57dc2140cfb62a8abb9312b89f02c59f3c
151+
```
152+
153+
154+
[`cargo-bisect-rustc`]: https://github.com/rust-lang-nursery/cargo-bisect-rustc
155+
[issue #53157]: https://github.com/rust-lang/rust/issues/53157
156+
[issue #55036]: https://github.com/rust-lang/rust/issues/55036

0 commit comments

Comments
 (0)