Bisection boundaries
cargo-bisect-rustc
does a binary search for the regression using a start and end boundary.
You can specify these boundaries with the --start
and --end
CLI flags.
There are several ways to specify what those boundaries are.
If you run the command without specifying the boundaries, it will search for them automatically:
# No --start or --end flags
cargo bisect-rustc
This will assume the latest nightly is a regression (the end boundary). It will then search backwards until it can find a nightly that passes to use as the start boundary. Bisection can usually go faster if you happen to know the start boundary, so that it doesn’t need to search for it.
--start
and --end
are optional.
If --start
is not specified, then it will try to find the start range automatically.
If --end
is not specified, it will assume it is the most recently available.
Date boundaries
You can pass a date in the form YYYY-MM-DD to the --start
and --end
flags.
It will download the nightly corresponding to that date, and then begin bisecting those nightlies.
cargo bisect-rustc --start=2018-08-14 --end=2018-10-11
If the nightly with the regression was within the past 167 days, then it will automatically start bisecting the individual PRs merged on that day using Git commit boundaries.
Git commit boundaries
You can pass the particular git commit hash of a PR as a boundary. The Rust project keeps the builds of every merged PR for the last 167 days. If you happen to know the PR to use as a boundary, you can pass the SHA-1 hash of that PR.
cargo bisect-rustc \
--start=6323d9a45bdf0ac2a9319a6a558537e0a7e6abd1 \
--end=866a713258915e6cbb212d135f751a6a8c9e1c0a
There are several ways to determine the SHA-1 hash for a PR.
- On the PR itself, you should see a message like “bors merged commit c50c62d into
rust-lang:master
”. You can copy that hash to use as a boundary. If the PR was merged as part of a rollup, you will need to use the hash of the rollup instead. You’ll need to look through the PR messages to see if the PR was mentioned from a rollup PR. - In the rust repo, run
git log --first-parent upstream/master
(whereupstream
is your origin name forrust-lang/rust
). This will show all the top-level commits. You can then search for your PR.
Note: If the PR was merged after the most recent nightly, you’ll need to be sure to also specify the
--end
range. Otherwise it will assume the most recent nightly is the end and it won’t work if the start is after the end.
If the regression is found in a rollup PR, then cargo-bisect-rustc
will bisect the individual PRs within the rollup.
This final bisection is only available for x86_64-unknown-linux-gnu
since it is using the builds made for the rustc performance tracker.
Note: If you specify date boundaries, then you can use the
--by-commit
CLI option to force it to use PR commits instead of nightlies.
Git tag boundaries
The boundary can be specified with a git release tag.
This is useful if you know something works in one release and not another, but you don’t happen to know which nightly this corresponds with.
When given a tag, cargo-bisect-rustc
will try to find the nightly that corresponds with that release.
For example:
cargo bisect-rustc --start=1.58.0 --end=1.59.0
Monotonicity
When writing your test and picking a bisection range, you should be careful to ensure that the test won’t vary between pass/fail over the bisection range. It should only transition from good to bad once in the bisection range (it must change monotonically).
In the following example, cargo-bisect-rustc
will find one of the transitions, but that may not be the true root cause of the issue you are investigating.
nightly-2023-02-01 baseline **start**
nightly-2023-02-02 baseline
nightly-2023-02-03 baseline
nightly-2023-02-04 regression
nightly-2023-02-05 regression
nightly-2023-02-06 baseline
nightly-2023-02-07 regression
nightly-2023-02-08 regression **end**
Here it may either find 2023-02-04 or 2023-02-07 as the regression.
The following are some suggestions for avoiding or dealing with this problem:
- Make sure your test reliably exhibits the issue you are looking for, and does not generate any false positives or false negatives.
- Analyze the PR that was reported as the regression. Do the changes in the PR seem to be a probable cause?
- Try to keep the bisection range small to reduce the probability that you will encounter multiple regression transitions.
- Use the
-vv
flag (very verbose) to display the output from the compiler to make sure it is what you expect. - Use the
--prompt
flag to inspect the output and verify each step. - Beware that some issues may get fixed and then regress multiple times. Try to keep the bisection range as close to the present day as possible. Compare the output of the “regressed” commit to the latest nightly to see if they are the same.
- If the test only fails sporadically, use a script to run the compiler many times until it fails or it passes enough iterations that you feel confident that it is good.
- If the code requires relatively new language features, be careful not to pick a starting range that is too old.
- Beware of code-generation bugs that can be sensitive to code layout. Since the code to rustc changes rapidly over time, code can shift around causing different layouts and optimizations, which might cause an issue to appear and disappear several times over the bisection range.