├── .github
├── dependabot.yml
└── workflows
│ ├── ci.yml
│ ├── docs.yml
│ └── publish.yml
├── .gitignore
├── CHANGELOG.md
├── Cargo.lock
├── Cargo.toml
├── LICENSE-APACHE
├── LICENSE-MIT
├── MAINTAINING.md
├── README.md
├── TUTORIAL.md
├── build.rs
├── guide
├── .gitignore
├── book.toml
└── src
│ ├── SUMMARY.md
│ ├── alt.md
│ ├── boundaries.md
│ ├── examples
│ ├── clippy.md
│ ├── components.md
│ ├── diagnostics.md
│ ├── doc-change.md
│ ├── flaky.md
│ ├── incremental.md
│ ├── index.md
│ ├── preserve.md
│ ├── rustdoc.md
│ ├── slow.md
│ ├── windows-scripting.md
│ └── without-cargo.md
│ ├── git-bisect.md
│ ├── installation.md
│ ├── introduction.md
│ ├── rust-src-repo.md
│ ├── rustup.md
│ ├── tutorial.md
│ └── usage.md
├── src
├── bounds.rs
├── git.rs
├── github.rs
├── least_satisfying.rs
├── main.rs
├── repo_access.rs
└── toolchains.rs
└── tests
├── README.md
├── cli_tests.rs
└── cmd
├── bare-h.stderr
├── bare-h.stdout
├── bare-h.toml
├── bare-help.stderr
├── bare-help.stdout
├── bare-help.toml
├── by-commit-no-start.stderr
├── by-commit-no-start.stdout
├── by-commit-no-start.toml
├── end-before-start.stderr
├── end-before-start.stdout
├── end-before-start.toml
├── end-in-future.stderr
├── end-in-future.stdout
├── end-in-future.toml
├── h.stderr
├── h.stdout
├── h.toml
├── help.stderr
├── help.stdout
├── help.toml
├── mixed-commit-date.stderr
├── mixed-commit-date.stdout
├── mixed-commit-date.toml
├── mixed-date-commit.stderr
├── mixed-date-commit.stdout
├── mixed-date-commit.toml
├── start-and-end-in-future.stderr
├── start-and-end-in-future.stdout
├── start-and-end-in-future.toml
├── start-in-future.stderr
├── start-in-future.stdout
└── start-in-future.toml
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "cargo"
4 | directory: "/"
5 | schedule:
6 | interval: "weekly"
7 | open-pull-requests-limit: 20
8 | ignore:
9 | - dependency-name: "*"
10 | update-types: ["version-update:semver-patch"]
11 | - package-ecosystem: "github-actions"
12 | directory: "/"
13 | schedule:
14 | interval: "weekly"
15 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 | on:
3 | pull_request:
4 | push:
5 | branches-ignore:
6 | - 'dependabot/**'
7 | permissions:
8 | contents: read
9 | jobs:
10 | test:
11 | name: Test
12 | strategy:
13 | matrix:
14 | os: ["ubuntu-latest", "windows-latest", "macos-latest"]
15 | rust: ["stable"]
16 | runs-on: ${{ matrix.os }}
17 | steps:
18 | - name: Checkout repository
19 | uses: actions/checkout@v4
20 | - name: Install Rust
21 | uses: dtolnay/rust-toolchain@master
22 | with:
23 | toolchain: ${{ matrix.rust }}
24 | - uses: Swatinem/rust-cache@v2
25 | - name: Build
26 | run: cargo test --no-run
27 | - name: Test
28 | env:
29 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30 | run: cargo test
31 | - name: Verify that binary works
32 | run: |
33 | cargo run -- bisect-rustc --help | grep "Examples:"
34 |
35 | fmt:
36 | name: rustfmt
37 | runs-on: ubuntu-latest
38 | steps:
39 | - name: Checkout source
40 | uses: actions/checkout@v4
41 | - name: Install Rust
42 | uses: dtolnay/rust-toolchain@stable
43 | with:
44 | components: rustfmt
45 | - name: Run rustfmt check
46 | run: |
47 | cargo fmt --version
48 | cargo fmt --check || (echo "Please reformat your code with 'cargo fmt' (version $(cargo fmt --version))"; false)
49 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: Documentation Deploy
2 | on:
3 | push:
4 | branches:
5 | - master
6 |
7 | permissions:
8 | contents: read
9 |
10 | jobs:
11 | deploy:
12 | permissions:
13 | contents: write # for Git to git push
14 | runs-on: ubuntu-latest
15 | env:
16 | MDBOOK_VERSION: 0.4.51
17 | steps:
18 | - uses: actions/checkout@v4
19 | with:
20 | fetch-depth: 0
21 | - name: Install mdbook
22 | run: |
23 | mkdir mdbook
24 | curl -Lf https://github.com/rust-lang/mdBook/releases/download/v${MDBOOK_VERSION}/mdbook-v${MDBOOK_VERSION}-x86_64-unknown-linux-gnu.tar.gz | tar -xz --directory=./mdbook
25 | echo `pwd`/mdbook >> $GITHUB_PATH
26 | - name: Deploy docs
27 | run: |
28 | cd guide
29 | mdbook build
30 | git worktree add gh-pages
31 | git config user.name "Deploy from CI"
32 | git config user.email ""
33 | cd gh-pages
34 | # Delete the ref to avoid keeping history.
35 | git update-ref -d refs/heads/gh-pages
36 | rm -rf *
37 | mv ../book/* .
38 | git add .
39 | git commit -m "Deploy $GITHUB_SHA to gh-pages"
40 | git push --force --set-upstream origin gh-pages
41 |
--------------------------------------------------------------------------------
/.github/workflows/publish.yml:
--------------------------------------------------------------------------------
1 | name: Publish
2 | on:
3 | release:
4 | types: [created]
5 |
6 | defaults:
7 | run:
8 | shell: bash
9 |
10 | permissions:
11 | contents: read
12 |
13 | jobs:
14 | publish:
15 | name: Publish to crates.io
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@v4
19 | - name: Install Rust (rustup)
20 | run: rustup update stable --no-self-update && rustup default stable
21 | - name: Publish
22 | env:
23 | CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
24 | run: cargo publish --no-verify
25 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /rust.git
2 | /target
3 | **/*.rs.bk
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | ## v0.6.10
4 | [v0.6.9...v0.6.10](https://github.com/rust-lang/cargo-bisect-rustc/compare/v0.6.9...v0.6.10)
5 |
6 | ### Added
7 | - Added the `--pretend-to-be-stable` flag.
8 | [#335](https://github.com/rust-lang/cargo-bisect-rustc/pull/335)
9 | - Documented how to bisect an individual clippy warning.
10 | [#368](https://github.com/rust-lang/cargo-bisect-rustc/pull/368)
11 | - Documented another example of a hanging compilation.
12 | [#374](https://github.com/rust-lang/cargo-bisect-rustc/pull/374)
13 |
14 | ### Changed
15 | - Print the command that is run with `--verbose`.
16 | [#361](https://github.com/rust-lang/cargo-bisect-rustc/pull/361)
17 | - Updated all dependencies.
18 | [#383](https://github.com/rust-lang/cargo-bisect-rustc/pull/383)
19 | - Unrolled CI builds have moved from the `rust-lang-ci/rust` repository to the `rust-lang/rust` repository.
20 | [#381](https://github.com/rust-lang/cargo-bisect-rustc/pull/381)
21 |
22 | ### Fixed
23 | - Fixed printing of args in the final report.
24 | [#356](https://github.com/rust-lang/cargo-bisect-rustc/pull/356)
25 | - Fixed so that `cargo-bisect-rustc` can be run with the hyphen after `cargo` or a space.
26 | [#362](https://github.com/rust-lang/cargo-bisect-rustc/pull/362)
27 |
28 | ## v0.6.9
29 |
30 | ### Added
31 | - Added flags `--term-old` and `--term-new` to allow custom messages when bisecting a regression.
32 | [#330](https://github.com/rust-lang/cargo-bisect-rustc/pull/330)
33 | [#339](https://github.com/rust-lang/cargo-bisect-rustc/pull/339)
34 |
35 |
36 | ### Changed
37 | - Updated dependencies.
38 | [#314](https://github.com/rust-lang/cargo-bisect-rustc/pull/314)
39 | [#313](https://github.com/rust-lang/cargo-bisect-rustc/pull/313)
40 | [#315](https://github.com/rust-lang/cargo-bisect-rustc/pull/315)
41 | [#319](https://github.com/rust-lang/cargo-bisect-rustc/pull/319)
42 | [#326](https://github.com/rust-lang/cargo-bisect-rustc/pull/326)
43 | [#327](https://github.com/rust-lang/cargo-bisect-rustc/pull/327)
44 | [#329](https://github.com/rust-lang/cargo-bisect-rustc/pull/329)
45 | [#340](https://github.com/rust-lang/cargo-bisect-rustc/pull/340)
46 | - No longer defaults to cross-compile mode when `--target` is not specified. This more closely matches `cargo`'s behavior, which can affect reproducability.
47 | [#323](https://github.com/rust-lang/cargo-bisect-rustc/pull/323)
48 | - Removed LTO and stripping of building `cargo-bisect-rustc` itself.
49 | [#334](https://github.com/rust-lang/cargo-bisect-rustc/pull/334)
50 |
51 | ### Fixed
52 | - Don't assume the date before the regressed nightly is the good nightly if there are missing nightlies.
53 | [#320](https://github.com/rust-lang/cargo-bisect-rustc/pull/320)
54 | - Fixed building `cargo-bisect-rustc` itself to avoid unnecessary build-script rebuilds.
55 | [#324](https://github.com/rust-lang/cargo-bisect-rustc/pull/324)
56 | - Fixed doc-change example documentation.
57 | [#336](https://github.com/rust-lang/cargo-bisect-rustc/pull/336)
58 | - Replaced a panic with an error message if a given SHA commit is not from bors using the GitHub backend.
59 | [#318](https://github.com/rust-lang/cargo-bisect-rustc/pull/318)
60 | - Fixed determination of what the latest nightly is when `--end` is not specified, and it is past UTC midnight, but the release process has not yet finished.
61 | [#325](https://github.com/rust-lang/cargo-bisect-rustc/pull/325)
62 | - Fixed panic with `--by-commit` but no `--start`.
63 | [#325](https://github.com/rust-lang/cargo-bisect-rustc/pull/325)
64 |
65 | ## v0.6.8
66 |
67 | ### Added
68 | - Added documentation for `--alt` builds.
69 | [#289](https://github.com/rust-lang/cargo-bisect-rustc/pull/289)
70 |
71 | ### Changed
72 | - ❗️ Changed the default access method to "github", meaning it will use the GitHub API to fetch commit information instead of using a local git clone. See the [access documentation](https://rust-lang.github.io/cargo-bisect-rustc/rust-src-repo.html) for more information.
73 | [#307](https://github.com/rust-lang/cargo-bisect-rustc/pull/307)
74 | - Updated dependencies.
75 | [#290](https://github.com/rust-lang/cargo-bisect-rustc/pull/290)
76 | [#291](https://github.com/rust-lang/cargo-bisect-rustc/pull/291)
77 | [#296](https://github.com/rust-lang/cargo-bisect-rustc/pull/296)
78 | [#302](https://github.com/rust-lang/cargo-bisect-rustc/pull/302)
79 | [#301](https://github.com/rust-lang/cargo-bisect-rustc/pull/301)
80 | [#300](https://github.com/rust-lang/cargo-bisect-rustc/pull/300)
81 | [#304](https://github.com/rust-lang/cargo-bisect-rustc/pull/304)
82 | [#305](https://github.com/rust-lang/cargo-bisect-rustc/pull/305)
83 | [#306](https://github.com/rust-lang/cargo-bisect-rustc/pull/306)
84 | [#308](https://github.com/rust-lang/cargo-bisect-rustc/pull/308)
85 |
86 | ## Fixed
87 | - Fixed an issue when attempting to bisect a rollup, but the perf commits have been garbage collected, to display information about the rollup so that you can see which PRs were involved.
88 | [#298](https://github.com/rust-lang/cargo-bisect-rustc/pull/298)
89 |
90 | ## v0.6.7
91 |
92 | ### Changed
93 | - Updated dependencies.
94 | [#271](https://github.com/rust-lang/cargo-bisect-rustc/pull/271)
95 | [#270](https://github.com/rust-lang/cargo-bisect-rustc/pull/270)
96 | [#273](https://github.com/rust-lang/cargo-bisect-rustc/pull/273)
97 | [#278](https://github.com/rust-lang/cargo-bisect-rustc/pull/278)
98 | [#279](https://github.com/rust-lang/cargo-bisect-rustc/pull/279)
99 | [#281](https://github.com/rust-lang/cargo-bisect-rustc/pull/281)
100 | [#285](https://github.com/rust-lang/cargo-bisect-rustc/pull/285)
101 | - CI artifacts are now downloaded from https://ci-artifacts.rust-lang.org instead of https://s3-us-west-1.amazonaws.com/rust-lang-ci2 which should help with performance.
102 |
103 | ### Fixed
104 | - Fix bisecting into rollups via unrolled perf builds
105 | [#280](https://github.com/rust-lang/cargo-bisect-rustc/pull/280)
106 |
107 | ## v0.6.6
108 |
109 | ### Added
110 |
111 | - 🎉 Added bisecting of rollups. This depends on the artifacts generated for rustc-perf which is only available for x86_64-unknown-linux-gnu.
112 | [#256](https://github.com/rust-lang/cargo-bisect-rustc/pull/256)
113 | - 🎉 Added a new User Guide with more detailed documentation and a set of examples illustrating different ways to use `cargo-bisect-rustc`. The guide is available at .
114 | [#266](https://github.com/rust-lang/cargo-bisect-rustc/pull/266)
115 |
116 | ### Changed
117 |
118 | - Added another kind of ICE output that is auto-detected.
119 | [#261](https://github.com/rust-lang/cargo-bisect-rustc/pull/261)
120 | - Updated dependencies:
121 | - tokio [#245](https://github.com/rust-lang/cargo-bisect-rustc/pull/245) [#255](https://github.com/rust-lang/cargo-bisect-rustc/pull/255)
122 | - git2 [#246](https://github.com/rust-lang/cargo-bisect-rustc/pull/246) [#249](https://github.com/rust-lang/cargo-bisect-rustc/pull/249)
123 | - bumpalo [#250](https://github.com/rust-lang/cargo-bisect-rustc/pull/250)
124 | - pbr [#257](https://github.com/rust-lang/cargo-bisect-rustc/pull/257)
125 | - tempfile [#260](https://github.com/rust-lang/cargo-bisect-rustc/pull/260)
126 | - openssl [#267](https://github.com/rust-lang/cargo-bisect-rustc/pull/267)
127 | - chrono [#268](https://github.com/rust-lang/cargo-bisect-rustc/pull/268)
128 |
129 | ### Fixed
130 |
131 | - Fixed bounds checking when `--start` or `--end` is not specified.
132 | [#243](https://github.com/rust-lang/cargo-bisect-rustc/pull/243)
133 | - The remote tags are now fetched from the `rust-lang/rust` repo to ensure that tag boundaries (`--start 1.65.0`) work if the tag hasn't been downloaded.
134 | [#263](https://github.com/rust-lang/cargo-bisect-rustc/pull/263)
135 |
136 | ## v0.6.5
137 |
138 | ### Changed
139 |
140 | - Stack overflow on any thread (not just 'rustc') is treated as an ICE.
141 | [#194](https://github.com/rust-lang/cargo-bisect-rustc/pull/194)
142 | - Clap (the CLI argument processor) has been updated, which may result in some minor CLI output and parsing changes.
143 | [#225](https://github.com/rust-lang/cargo-bisect-rustc/pull/225)
144 | [#229](https://github.com/rust-lang/cargo-bisect-rustc/pull/229)
145 | - The check for the Rust upstream remote in the git repository has been loosened to only scan for `rust-lang/rust` so that non-https remotes like `git@github.com:rust-lang/rust.git` will work.
146 | [#235](https://github.com/rust-lang/cargo-bisect-rustc/pull/235)
147 | - The `--script` option will now look for a script in the current directory (so that it no longer requires the `./` prefix).
148 | [#236](https://github.com/rust-lang/cargo-bisect-rustc/pull/236)
149 | [#238](https://github.com/rust-lang/cargo-bisect-rustc/pull/238)
150 | - Specifying `--start` without `--end` will default the end to be the current date. Previously it would use the date of whatever nightly is currently installed.
151 | [#240](https://github.com/rust-lang/cargo-bisect-rustc/pull/240)
152 |
153 | ### Fixed
154 |
155 | - Fixed using either `cargo bisect-rustc` (with a space) or `cargo-bisect-rustc` (with a dash).
156 | [#187](https://github.com/rust-lang/cargo-bisect-rustc/pull/187)
157 | - Show the CLI help page if no arguments are passed.
158 | [#206](https://github.com/rust-lang/cargo-bisect-rustc/pull/206)
159 | - The CLI argument validator for `--script` has been removed to allow running scripts on PATH. This also removes the `--host` validator which was not needed.
160 | [#207](https://github.com/rust-lang/cargo-bisect-rustc/pull/207)
161 | - Fixed showing the full chain of errors instead of just the top-level one.
162 | [#237](https://github.com/rust-lang/cargo-bisect-rustc/pull/237)
163 |
164 | ## v0.6.4
165 |
166 | ### Added
167 |
168 | - Added the `--component` option to choose optional components to install.
169 | [#131](https://github.com/rust-lang/cargo-bisect-rustc/pull/131)
170 | - An estimate of the number of steps left to run is now displayed.
171 | [#178](https://github.com/rust-lang/cargo-bisect-rustc/pull/178)
172 |
173 | ### Changed
174 |
175 | - Various code refactorings and dependency updates. These shouldn't have
176 | significant noticeable changes.
177 | [#151](https://github.com/rust-lang/cargo-bisect-rustc/pull/151)
178 | [#152](https://github.com/rust-lang/cargo-bisect-rustc/pull/152)
179 | [#153](https://github.com/rust-lang/cargo-bisect-rustc/pull/153)
180 | [#155](https://github.com/rust-lang/cargo-bisect-rustc/pull/155)
181 | [#156](https://github.com/rust-lang/cargo-bisect-rustc/pull/156)
182 | - The `CARGO_BUILD_TARGET` environment variable is now set with the target triple.
183 | [#159](https://github.com/rust-lang/cargo-bisect-rustc/pull/159)
184 | - The default release profile now uses stripping and LTO to significantly
185 | reduce the binary size.
186 | [#157](https://github.com/rust-lang/cargo-bisect-rustc/pull/157)
187 | - Bounds with tags like `--start=1.62.0` are now translated to a nightly date
188 | instead of a master git commit. This allows using tags from releases more
189 | than 6 months old.
190 | [#177](https://github.com/rust-lang/cargo-bisect-rustc/pull/177)
191 |
192 | ## v0.6.3
193 |
194 | ### Fixed
195 |
196 | - Fixed assumption that the rust-lang/rust remote repo is named "origin".
197 | [#149](https://github.com/rust-lang/cargo-bisect-rustc/pull/149)
198 |
199 | ## v0.6.2
200 |
201 | ### Added
202 |
203 | - `--start` and `--end` now support git tags (like `1.59.0`) to bisect between stable releases.
204 | [#147](https://github.com/rust-lang/cargo-bisect-rustc/pull/147)
205 |
206 | ### Changed
207 |
208 | - Stack overflow is now treated as an ICE.
209 | [#142](https://github.com/rust-lang/cargo-bisect-rustc/pull/142)
210 |
211 | ## v0.6.1
212 |
213 | ### Added
214 |
215 | - Added `--with-dev` option to download rustc-dev component.
216 | [#101](https://github.com/rust-lang/cargo-bisect-rustc/pull/101)
217 | - Added `--timeout` option to trigger a failure if compilation takes too long.
218 | [#135](https://github.com/rust-lang/cargo-bisect-rustc/pull/135)
219 |
220 | ### Changed
221 | - Use the `git` CLI to fetch the `rust-lang/rust` repo when looking for CI commits to improve performance.
222 | [#130](https://github.com/rust-lang/cargo-bisect-rustc/pull/130)
223 |
224 | ### Fixed
225 |
226 | - Fixed off-by-one error when examining the date of the local nightly toolchain.
227 | [#113](https://github.com/rust-lang/cargo-bisect-rustc/pull/113)
228 | - Fixed issue with `--preserve` when linking the nightly toolchain leaving a stale link.
229 | [#125](https://github.com/rust-lang/cargo-bisect-rustc/pull/125)
230 |
231 | ## v0.6.0
232 |
233 | ### Added
234 |
235 | - Support specifying the path to a rust-lang/rust clone at runtime with `RUST_SRC_REPO`
236 |
237 | ### Changed
238 |
239 | - Make `--with-cargo` the default to allow bisecting past changes in rustc options. Add `--without-cargo` flag to use the old behavior.
240 | - Use an anonymous remote that always points to rust-lang/rust when refreshing repository
241 |
242 | ### Fixed
243 |
244 | - Add nightly start and end date validations against the current date – previously would attempt to install nightly even if date was in the future
245 | - Verify that `--test-dir` is a directory instead of assuming it is and then panicking
246 |
247 | ## v0.5.2
248 |
249 | - Fix: revert the revised internal compiler error definition in commit a3891cdd26d1c5d35257c351c7c86fa7e72604bb
250 |
251 | ## v0.5.1
252 |
253 | - Fix: Windows build fails due to dependency of `console` dependency issue. Updated `winapi-util` package to v0.1.5 (from 0.1.2)
254 |
255 | ## v0.5.0
256 |
257 | - New: include compiler crashes in ICE regression definition
258 | - New: ANSI escape code colored standard stream output
259 | - New: Add bisect-rustc version to the final report
260 | - New: Add host triple to the final report
261 | - New: Add command line args to reproduce the reporter's bisect-rustc tests to final report
262 | - Fix: end date reporting when `--end` option used without `--start` option
263 | - Updated: Standard stream reporting format for improved readability during execution
264 | - Updated: Final report instructions for regression reporting
265 | - Updated: Eliminated Markdown elements in the final report that are not typically included in rust-lang/rust issues by reporting users
266 |
267 | ## v0.4.1
268 |
269 | - Fix: bug on git commit retrieval from local rust git repository when `--end` commit is not specified
270 | - Fix: bug on git commit retrieval from GitHub API when `--end` commit is not specified
271 | - Updated dependencies
272 | - rustfmt source code
273 |
274 | ## v0.4.0
275 |
276 | - Add support for GitHub API queries for Rust commit history
277 | - Add support for `--regress=non-ice` regression definition
278 | - Add support for `--script` arguments
279 | - Fix duplicated start date range pulls/checks
280 | - Reformat standard stream reporting
281 |
282 | ## v0.3.0
283 |
284 | - Transition to Rustlang edition 2018
285 | - Add test stage that can process output to decide outcome based on more subtle predicate than just `exit_status.success()`
286 | - Add support for optional `--regress=ice` regression testing definition (default is `--regress=error`)
287 | - Add support for optional `--regress=success` regression testing definition (default is `--regress=error`)
288 | - Add support for optional `--regress=non-error` regression testing definition (default is `--regress=error`)
289 | - Update the `remove` function to use an explicit `bisector` string at the beginning of the path name
290 | - Update the `remove` function to guard against deleting state not managed by `cargo-bisect-rustc`
291 | - Edit short and long help strings to fit on a single line
292 | - Fix: support reuse of an already installed nightly, previously we would unconditionally fail the run
293 |
294 | ## v0.2.1
295 |
296 | - Fix: refactor date bounds to assume that start date equals end date at the beginning of testing with `--end` option only
297 |
298 | ## v0.2.0
299 |
300 | - Add automated regression report generation at the end of the test runs
301 | - Add validation of date bounds
302 | - Updated dependencies to avoid yanked dependency versions
303 | - Improve documentation: Add documentation on how to list bors' commits for bisections to a PR
304 | - Improve documentation: Update tutorial
305 |
306 | ## v0.1.0
307 |
308 | - initial release
309 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | authors = ["Mark Simulacrum "]
3 | build = "build.rs"
4 | categories = ["development-tools"]
5 | description = "Bisects rustc toolchains with rustup"
6 | keywords = ["rustup"]
7 | license = "MIT OR Apache-2.0"
8 | name = "cargo-bisect-rustc"
9 | readme = "README.md"
10 | repository = "https://github.com/rust-lang/cargo-bisect-rustc"
11 | version = "0.6.10"
12 | edition = "2021"
13 |
14 | [dependencies]
15 | dialoguer = { version = "0.11.0", default-features = false }
16 | home = "0.5"
17 | env_logger = "0.11.0"
18 | thiserror = "2"
19 | anyhow = "1"
20 | flate2 = "1.1.0"
21 | git2 = "0.20.2"
22 | log = "0.4"
23 | pbr = "1.1.1"
24 | reqwest = { version = "0.12.1", features = ["blocking", "json"] }
25 | rustc_version = "0.4.0"
26 | serde = { version = "1.0.145", features = ["derive"] }
27 | serde_json = "1.0"
28 | clap = { version = "4.5", features = ["derive", "wrap_help"] }
29 | tar = "0.4"
30 | tee = "0.1"
31 | tempfile = "3.20.0"
32 | xz2 = "0.1.7"
33 | chrono = "0.4.22"
34 | colored = "3"
35 | regex = "1.11.0"
36 |
37 | [dev-dependencies]
38 | quickcheck = "1"
39 | trycmd = "0.15.0"
40 |
--------------------------------------------------------------------------------
/LICENSE-APACHE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Permission is hereby granted, free of charge, to any
2 | person obtaining a copy of this software and associated
3 | documentation files (the "Software"), to deal in the
4 | Software without restriction, including without
5 | limitation the rights to use, copy, modify, merge,
6 | publish, distribute, sublicense, and/or sell copies of
7 | the Software, and to permit persons to whom the Software
8 | is furnished to do so, subject to the following
9 | conditions:
10 |
11 | The above copyright notice and this permission notice
12 | shall be included in all copies or substantial portions
13 | of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 | DEALINGS IN THE SOFTWARE.
24 |
--------------------------------------------------------------------------------
/MAINTAINING.md:
--------------------------------------------------------------------------------
1 | # Maintaining cargo-bisect-rustc
2 |
3 | ## Publishing
4 |
5 | To publish a new release:
6 |
7 | 1. Create a PR to bump the version in `Cargo.toml` and `Cargo.lock`, and update [`CHANGELOG.md`](CHANGELOG.md).
8 | 2. After the merge is complete, create a new release. There are two approaches:
9 | - GUI: Create a new release in the UI, tag and title should be `v` and the version number. Copy a link to the changelog.
10 | - CLI: Run the following in the repo:
11 | ```bash
12 | VERSION="`cargo read-manifest | jq -r .version`" ; \
13 | gh release create -R rust-lang/cargo-bisect-rustc v$VERSION \
14 | --title v$VERSION \
15 | --notes "See https://github.com/rust-lang/cargo-bisect-rustc/blob/master/CHANGELOG.md#v${VERSION//.} for a complete list of changes."
16 | ```
17 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Cargo Bisection
2 |
3 | [](https://github.com/rust-lang/cargo-bisect-rustc/actions/workflows/ci.yml)
4 |
5 | This tool bisects either Rust nightlies or CI artifacts.
6 |
7 | [**Documentation**](https://rust-lang.github.io/cargo-bisect-rustc/)
8 |
9 | To run the documentation book locally, install [mdBook](https://github.com/rust-lang/mdBook):
10 |
11 | ``` sh
12 | cd guide
13 | mdbook serve # launch a local server to allow you to easily see and update changes you make
14 | mdbook build # build the book HTML
15 | ```
16 |
17 | ## License
18 |
19 | Licensed under either of
20 |
21 | * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or https://www.apache.org/licenses/LICENSE-2.0)
22 | * MIT license ([LICENSE-MIT](LICENSE-MIT) or https://opensource.org/licenses/MIT)
23 |
24 | at your option.
25 |
26 | ### Contribution
27 |
28 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
29 | work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any
30 | additional terms or conditions.
31 |
--------------------------------------------------------------------------------
/TUTORIAL.md:
--------------------------------------------------------------------------------
1 | # Tutorial
2 |
3 | The tutorial has moved to the new guide at .
4 |
--------------------------------------------------------------------------------
/build.rs:
--------------------------------------------------------------------------------
1 | use std::env;
2 |
3 | fn main() {
4 | println!("cargo:rustc-env=HOST={}", env::var("TARGET").unwrap());
5 | // Prevents cargo from scanning the whole directory for changes.
6 | println!("cargo:rerun-if-changed=build.rs");
7 | }
8 |
--------------------------------------------------------------------------------
/guide/.gitignore:
--------------------------------------------------------------------------------
1 | book
2 |
--------------------------------------------------------------------------------
/guide/book.toml:
--------------------------------------------------------------------------------
1 | [book]
2 | language = "en"
3 | multilingual = false
4 | src = "src"
5 | title = "cargo-bisect-rustc"
6 |
7 | [output.html]
8 | curly-quotes = true
9 | git-repository-url = "https://github.com/rust-lang/cargo-bisect-rustc/tree/master/guide/src"
10 | edit-url-template = "https://github.com/rust-lang/cargo-bisect-rustc/edit/master/guide/{path}"
11 |
--------------------------------------------------------------------------------
/guide/src/SUMMARY.md:
--------------------------------------------------------------------------------
1 | # Summary
2 |
3 | - [Introduction](introduction.md)
4 | - [Installation](installation.md)
5 | - [Basic usage](usage.md)
6 | - [Tutorial](tutorial.md)
7 | - [Rust source repo](rust-src-repo.md)
8 | - [Bisection boundaries](boundaries.md)
9 | - [Rustup toolchains](rustup.md)
10 | - [Git bisect a custom build](git-bisect.md)
11 | - [Alt builds](alt.md)
12 | - [Examples](examples/index.md)
13 | - [Checking diagnostics](examples/diagnostics.md)
14 | - [Scripting on Windows](examples/windows-scripting.md)
15 | - [Incremental compilation](examples/incremental.md)
16 | - [Slow or hung compilation](examples/slow.md)
17 | - [Using extra components](examples/components.md)
18 | - [Running without Cargo](examples/without-cargo.md)
19 | - [Preserving toolchains](examples/preserve.md)
20 | - [Bisecting Rustdoc](examples/rustdoc.md)
21 | - [Bisecting Clippy](examples/clippy.md)
22 | - [Documentation changes](examples/doc-change.md)
23 | - [Flaky errors](examples/flaky.md)
24 |
--------------------------------------------------------------------------------
/guide/src/alt.md:
--------------------------------------------------------------------------------
1 | # Alt builds
2 |
3 | Each commit also generates what are called "alt" builds.
4 | These are builds of rustc with some different options set.
5 | As of August 2023, these include:
6 |
7 | * `rust.parallel-compiler`
8 | * `llvm.assertions`
9 | * `rust.verify-llvm-ir`
10 |
11 | For more information on these settings, see the [`config.toml` docs].
12 | These alt settings are defined in [`ci/run.sh`].
13 |
14 | Alt builds are only available for a few targets.
15 | Look for the `-alt` builds in [`ci.yml`].
16 |
17 | This can be useful if you are bisecting an LLVM issue.
18 | With LLVM assertions enabled, alt builds have checks that can help identify broken assumptions.
19 |
20 | Alt builds are only made for commit builds, and not nightly releases.
21 | You will need to specify `--by-commit` (or use a hash in the `--start` or `--end` flags) to only use commit builds.
22 |
23 | ```sh
24 | cargo bisect-rustc --alt --by-commit
25 | ```
26 |
27 | [`config.toml` docs]: https://github.com/rust-lang/rust/blob/master/config.example.toml
28 | [`ci/run.sh`]: https://github.com/rust-lang/rust/blob/c0b6ffaaea3ebdf5f7a58fc4cf7ee52c91077fb9/src/ci/run.sh#L99-L105
29 | [`ci.yml`]: https://github.com/rust-lang/rust/blob/HEAD/src/ci/github-actions/ci.yml
30 |
--------------------------------------------------------------------------------
/guide/src/boundaries.md:
--------------------------------------------------------------------------------
1 | # Bisection boundaries
2 |
3 | `cargo-bisect-rustc` does a binary search for the regression using a *start* and *end* boundary.
4 | You can specify these boundaries with the `--start` and `--end` CLI flags.
5 | There are several ways to specify what those boundaries are.
6 | If you run the command without specifying the boundaries, it will search for them automatically:
7 |
8 | ```sh
9 | # No --start or --end flags
10 | cargo bisect-rustc
11 | ```
12 |
13 | This will assume the latest nightly is a regression (the *end* boundary).
14 | It will then search backwards until it can find a nightly that passes to use as the *start* boundary.
15 | Bisection can usually go faster if you happen to know the start boundary, so that it doesn't need to search for it.
16 |
17 | `--start` and `--end` are optional.
18 | If `--start` is not specified, then it will try to find the start range automatically.
19 | If `--end` is not specified, it will assume it is the most recently available.
20 |
21 | ## Date boundaries
22 |
23 | You can pass a date in the form YYYY-MM-DD to the `--start` and `--end` flags.
24 | It will download the nightly corresponding to that date, and then begin bisecting those nightlies.
25 |
26 | ```sh
27 | cargo bisect-rustc --start=2018-08-14 --end=2018-10-11
28 | ```
29 |
30 | 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).
31 |
32 | ## Git commit boundaries
33 |
34 | You can pass the particular git commit hash of a PR as a boundary.
35 | The Rust project keeps the builds of every merged PR for the last 167 days.
36 | If you happen to know the PR to use as a boundary, you can pass the SHA-1 hash of that PR.
37 |
38 | ```sh
39 | cargo bisect-rustc \
40 | --start=6323d9a45bdf0ac2a9319a6a558537e0a7e6abd1 \
41 | --end=866a713258915e6cbb212d135f751a6a8c9e1c0a
42 | ```
43 |
44 | There are several ways to determine the SHA-1 hash for a PR.
45 |
46 | - On the PR itself, you should see a message like "bors merged commit c50c62d into `rust-lang:master`".
47 | You can copy that hash to use as a boundary.
48 | If the PR was merged as part of a rollup, you will need to use the hash of the rollup instead.
49 | You'll need to look through the PR messages to see if the PR was mentioned from a rollup PR.
50 | - In the rust repo, run `git log --first-parent upstream/master` (where `upstream` is your origin name for `rust-lang/rust`).
51 | This will show all the top-level commits.
52 | You can then search for your PR.
53 |
54 | > **Note**: If the PR was merged after the most recent nightly, you'll need to be sure to also specify the `--end` range.
55 | > Otherwise it will assume the most recent nightly is the *end* and it won't work if the start is after the end.
56 |
57 | If the regression is found in a [rollup PR], then `cargo-bisect-rustc` will bisect the individual PRs within the rollup.
58 | This final bisection is only available for `x86_64-unknown-linux-gnu` since it is using the builds made for the [rustc performance tracker].
59 |
60 | > **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.
61 |
62 | [rollup PR]: https://forge.rust-lang.org/release/rollups.html
63 | [rustc performance tracker]: https://perf.rust-lang.org/
64 |
65 | ## Git tag boundaries
66 |
67 | The boundary can be specified with a git release tag.
68 | 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.
69 | When given a tag, `cargo-bisect-rustc` will try to find the nightly that corresponds with that release.
70 | For example:
71 |
72 | ```sh
73 | cargo bisect-rustc --start=1.58.0 --end=1.59.0
74 | ```
75 |
76 | ## Monotonicity
77 |
78 | 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.
79 | It should only transition from good to bad once in the bisection range (it must change
80 | [monotonically]).
81 |
82 | 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.
83 |
84 | ```text
85 | nightly-2023-02-01 baseline **start**
86 | nightly-2023-02-02 baseline
87 | nightly-2023-02-03 baseline
88 | nightly-2023-02-04 regression
89 | nightly-2023-02-05 regression
90 | nightly-2023-02-06 baseline
91 | nightly-2023-02-07 regression
92 | nightly-2023-02-08 regression **end**
93 | ```
94 |
95 | Here it may either find 2023-02-04 or 2023-02-07 as the regression.
96 |
97 | The following are some suggestions for avoiding or dealing with this problem:
98 |
99 | - Make sure your test reliably exhibits the issue you are looking for, and does not generate any false positives or false negatives.
100 | - Analyze the PR that was reported as the regression.
101 | Do the changes in the PR seem to be a probable cause?
102 | - Try to keep the bisection range small to reduce the probability that you will encounter multiple regression transitions.
103 | - Use the `-vv` flag (very verbose) to display the output from the compiler to make sure it is what you expect.
104 | - Use the [`--prompt`](tutorial.md#testing-interactively) flag to inspect the output and verify each step.
105 | - Beware that some issues may get fixed and then regress multiple times.
106 | Try to keep the bisection range as close to the present day as possible.
107 | Compare the output of the "regressed" commit to the latest nightly to see if they are the same.
108 | - If the test only fails sporadically, use a [script](examples/flaky.md) to run the compiler many times until it fails or it passes enough iterations that you feel confident that it is good.
109 | - If the code requires relatively new language features, be careful not to pick a starting range that is too old.
110 | - Beware of code-generation bugs that can be sensitive to code layout.
111 | 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.
112 |
113 | [monotonically]: https://en.wikipedia.org/wiki/Bisection_(software_engineering)#Monotonicity
114 |
--------------------------------------------------------------------------------
/guide/src/examples/clippy.md:
--------------------------------------------------------------------------------
1 | # Bisecting clippy
2 |
3 | `cargo-bisect-rustc` can be used to check for Clippy regressions, too.
4 | You'll need to instruct it to download clippy, and run the command correctly:
5 |
6 | ```sh
7 | cargo bisect-rustc --start=1.67.0 --end=1.68.0 -c clippy -- clippy
8 | ```
9 |
10 | Note that depending on what you are looking for, this may just find a PR that syncs the [`rust-clippy`] repo to `rust-lang/rust`.
11 | You may be able to scan the list of changes in that PR to discover what you are looking for.
12 | If the list of changes is too big or nothing is jumping out as a possible culprit, then consider using [`git bisect`] on the clippy repo itself (which will require building clippy).
13 |
14 | To bisect a clippy warning, you can upgrade the warning to an error:
15 |
16 | ```sh
17 | cargo bisect-rustc --start=1.84.0 --end=1.85.0 -c clippy -- clippy -- --forbid clippy::useless_conversion
18 | ```
19 |
20 | [`rust-clippy`]: https://github.com/rust-lang/rust-clippy/
21 | [`git bisect`]: https://git-scm.com/docs/git-bisect
22 |
--------------------------------------------------------------------------------
/guide/src/examples/components.md:
--------------------------------------------------------------------------------
1 | # Using extra components
2 |
3 | By default, `cargo-bisect-rustc` only fetches `rustc`, `cargo`, `rustdoc`, and the standard library for the host.
4 | You may need additional [Rustup Components](https://rust-lang.github.io/rustup/concepts/components.html) to run your test.
5 | Some examples of when this might be needed are:
6 |
7 | * You want to find a regression in Clippy (see [Bisecting Clippy](clippy.md)), or miri.
8 | * Scanning for when some documentation changed (see [Documentation changes](doc-change.md)).
9 | * The platform needs additional things.
10 | For example, bisecting `x86_64-pc-windows-gnu` host may need the `rust-mingw` component.
11 |
12 | If you are testing cross-compilation, use the `--target` option to download the standard library for the target you are using.
13 |
14 | The following example shows how to use components to do a bisection with Cargo's [build-std](https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-std) feature.
15 |
16 | ```sh
17 | cargo-bisect-rustc --start=2022-11-01 --end=2022-11-20 -c rust-src -- build -Zbuild-std
18 | ```
19 |
20 | > **Note**: The `--with-src` option is an alias for `-c rust-src`. \
21 | > The `--with-dev` option is an alias for `-c rustc-dev -c llvm-tools`.
22 |
--------------------------------------------------------------------------------
/guide/src/examples/diagnostics.md:
--------------------------------------------------------------------------------
1 | # Checking diagnostics
2 |
3 | The following is an example of checking when the diagnostic output of `rustc` *changes*.
4 | For example, this can check when either the wording has changed, or a different error or warning is produced.
5 |
6 | [#109067](https://github.com/rust-lang/rust/issues/109067) is an example of where this is necessary.
7 | A warning started being emitted, and it is the kind of warning that cannot be turned into an error with `deny(warnings)`.
8 |
9 | The following script is intended to be used with the `--script` option (set the executable flag on the script, `chmod u+x`):
10 |
11 | ```sh
12 | #!/bin/sh
13 |
14 | OUTPUT=`cargo check 2>&1`
15 | # Comment out this test if your example is intended to fail.
16 | if [ $? -ne 0 ]
17 | then
18 | echo "Build unexpectedly failed: $OUTPUT"
19 | exit 1
20 | fi
21 | # Display the output for debugging purposes.
22 | # Run `cargo-bisect-rustc` with `-vv` to view the output.
23 | echo "$OUTPUT"
24 | # This indicates a regression when the text "non-ASCII" is in the output.
25 | #
26 | # If the regression is when the text is *not* in the output, remove the `!` prefix
27 | # (and customize the `--term-old` and `--term-new` CLI options if you want).
28 | ! echo "$OUTPUT" | grep "non-ASCII"
29 | ```
30 |
31 | Then run something like:
32 |
33 | ```sh
34 | cargo bisect-rustc --start=1.67.0 --end=1.68.0 --script ./test.sh \
35 | --term-old="No warning" --term-new="Found non-ASCII warning"
36 | ```
37 |
--------------------------------------------------------------------------------
/guide/src/examples/doc-change.md:
--------------------------------------------------------------------------------
1 | # Documentation changes
2 |
3 | `cargo-bisect-rustc` can be used to scan for changes in the documentation shipped with each release.
4 | This includes all the books and standard library documentation.
5 | To do this, instruct it to download the component, and use a script that scans for whatever you are looking for.
6 | You can use `rustup doc --path` or `rustc --print=sysroot` to find the proper location.
7 | For example:
8 |
9 | `test.sh`:
10 | ```sh
11 | #!/bin/sh
12 |
13 | # Exit if any command fails.
14 | set -e
15 |
16 | STD=`dirname $(rustup doc --std --path)`
17 |
18 | # Checks if a particular file exists.
19 | # This could also be `grep` or any other kinds of tests you need.
20 | if [ -e $STD/io/error/type.RawOsError.html ]
21 | then
22 | echo "found"
23 | exit 1
24 | fi
25 | ```
26 |
27 | And run with:
28 |
29 | ```sh
30 | cargo bisect-rustc --start 1.68.0 --end 1.69.0 -c rust-docs --script ./test.sh \
31 | --term-old="Did not find" --term-new="Found"
32 | ```
33 |
34 | > **Note**: This may not work on all targets since `cargo-bisect-rustc` doesn't properly handle rustup manifests, which alias some targets to other targets.
35 | > Use `--host x86_64-unknown-linux-gnu` in that situation.
36 |
--------------------------------------------------------------------------------
/guide/src/examples/flaky.md:
--------------------------------------------------------------------------------
1 | # Flaky errors
2 |
3 | Some tests may fail randomly.
4 | The following script is an example that will run `rustc` repeatedly to check for a failure.
5 | This example is from [#108216](https://github.com/rust-lang/rust/issues/108216) (which requires macOS).
6 |
7 | `test.sh`:
8 | ```sh
9 | #!/bin/sh
10 |
11 | rm -rf *.o incremental foo
12 |
13 | echo "fn main() { let a: i64 = 1 << 64; }" > foo1.rs
14 | echo "fn main() { let a: i64 = 1 << 63; }" > foo2.rs
15 |
16 | ARGS="--crate-name foo -C split-debuginfo=unpacked -C debuginfo=2 -C incremental=incremental"
17 |
18 | for i in {1..20}
19 | do
20 | echo run $i
21 | rustc foo1.rs $ARGS && { echo "ERROR: first build should have failed"; exit 1; }
22 | rustc foo2.rs $ARGS || { echo "ERROR: second build should have passed"; exit 1; }
23 | ./foo || { echo "ERROR: executing should have passed"; exit 1; }
24 | done
25 | ```
26 |
27 | This test can be run with:
28 |
29 | ```sh
30 | cargo bisect-rustc --start=1.57.0 --end=1.58.0 --script=./test.sh
31 | ```
32 |
33 | In general, configure the script to perform whichever actions you need in a `for` loop that runs enough times that you have a high confidence it has found the regression.
34 |
--------------------------------------------------------------------------------
/guide/src/examples/incremental.md:
--------------------------------------------------------------------------------
1 | # Incremental compilation
2 |
3 | Testing for regressions with incremental compilation may require running a command multiple times.
4 | The following illustrates an example for [#87384](https://github.com/rust-lang/rust/issues/87384) which only generates a warning the second time a build is run with incremental.
5 | Previously no warning was emitted.
6 |
7 | `foo.rs`:
8 | ```rust
9 | #![type_length_limit = "95595489"]
10 |
11 | pub fn main() {
12 | println!("Hello, world!");
13 | }
14 | ```
15 |
16 | Create a script `test.sh`:
17 |
18 | ```sh
19 | #!/bin/sh
20 |
21 | # Exit if any command fails.
22 | set -e
23 |
24 | rm -rf incremental
25 | rustc foo.rs --crate-type lib -C incremental=incremental
26 | echo second
27 | OUTPUT=`rustc foo.rs --crate-type lib -C incremental=incremental 2>&1`
28 | echo $OUTPUT
29 | ! echo "$OUTPUT" | grep \
30 | "crate-level attribute should be in the root module"
31 | ```
32 |
33 | Run this script with:
34 |
35 | ```sh
36 | cargo-bisect-rustc --start 1.54.0 --end 1.55.0 --script ./test.sh
37 | ```
38 |
--------------------------------------------------------------------------------
/guide/src/examples/index.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | The following chapters show examples of different ways of using `cargo-bisect-rustc`.
4 |
--------------------------------------------------------------------------------
/guide/src/examples/preserve.md:
--------------------------------------------------------------------------------
1 | # Preserving toolchains
2 |
3 | You may want to reuse the toolchains downloaded by `cargo-bisect-rustc` for doing further analysis or debugging.
4 | Or, while setting up your regression test, you may need to adjust your test and script several times, and downloading the same toolchains multiple times can be quite slow.
5 |
6 | You can do this with the `--preserve` option.
7 |
8 | ```sh
9 | cargo bisect-rustc --start=2023-01-01 --end=2023-02-01 --preserve
10 | ```
11 |
12 | The toolchains will be kept in your Rustup home directory (typically `~/.rustup/toolchains`).
13 |
14 | Toolchains for nightlies will have the form of `bisector-nightly-YYYY-MM-DD-`.
15 | Toolchains for PR artifacts will have the form of `bisector-ci--`.
16 |
17 | You can run these toolchains using a Rustup override, like this:
18 |
19 | ```sh
20 | cargo +bisector-nightly-2023-03-18-x86_64-unknown-linux-gnu build
21 | # or...
22 | cargo +bisector-ci-e187f8871e3d553181c9d2d4ac111197a139ca0d-x86_64-unknown-linux-gnu build
23 | ```
24 |
25 | When you are done, you'll probably want to clean up these directories since they use a lot of space.
26 | The easiest method is to just delete the directories:
27 |
28 | ```sh
29 | rm -rf ~/.rustup/toolchains/bisector-*
30 | ```
31 |
32 | ## Manually installing
33 |
34 | The `--install` option can be used to only install a toolchain.
35 | This won't do a bisection, it is just for fetching a toolchain for testing.
36 |
37 | ```sh
38 | cargo bisect-rustc --install e187f8871e3d553181c9d2d4ac111197a139ca0d
39 | ```
40 |
41 | > **Note**: See also [`rustup-toolchain-install-master`](https://github.com/kennytm/rustup-toolchain-install-master) which is specialized for installing CI artifacts.
42 |
--------------------------------------------------------------------------------
/guide/src/examples/rustdoc.md:
--------------------------------------------------------------------------------
1 | # Bisecting Rustdoc
2 |
3 | `cargo-bisect-rustc` can be used to check for Rustdoc regressions, too.
4 | All you need to do is instruct it to use the correct command.
5 |
6 | The following example will check to find a regression when `cargo doc` suddenly starts to fail.
7 |
8 | ```sh
9 | cargo bisect-rustc --start=2022-08-05 --end=2022-09-09 -- doc
10 | ```
11 |
12 | Some rustdoc regressions might be in the generated HTML output.
13 | To scan the output, you can use a script like the following:
14 |
15 | `test.sh`:
16 | ```sh
17 | #!/bin/sh
18 |
19 | # Exit if any command fails.
20 | set -e
21 |
22 | cargo doc
23 |
24 | grep "some example text" $CARGO_TARGET_DIR/doc/mycrate/fn.foo.html
25 | ```
26 |
27 | This can be used with the `--script` option:
28 |
29 | ```sh
30 | cargo-bisect-rustc --start=2023-01-22 --end=2023-03-18 --script=./test.sh \
31 | --term-old="Found example text" --term-new="Failed, or did not find text"
32 | ```
33 |
--------------------------------------------------------------------------------
/guide/src/examples/slow.md:
--------------------------------------------------------------------------------
1 | # Slow or hung compilation
2 |
3 | Some regressions may involve the compiler hanging or taking an unusually long time to run.
4 | The `--timeout` CLI option can be used to check for this.
5 | Let's use [#89524](https://github.com/rust-lang/rust/issues/89524) as an example.
6 | A particular combination of factors caused the compiler to start to hang.
7 |
8 | Change `Cargo.toml` to the following:
9 |
10 | ```toml
11 | [package]
12 | name = "slow"
13 | version = "0.1.0"
14 |
15 | [dependencies]
16 | config = "=0.9.3"
17 |
18 | [profile.release]
19 | panic = "abort"
20 | codegen-units = 1
21 | ```
22 |
23 | Then use the timeout option:
24 |
25 | ```sh
26 | cargo-bisect-rustc --start=2021-09-01 --end=2021-10-02 --timeout 30 -- build --release
27 | ```
28 |
29 | You may need to adjust the timeout value based on the speed of your system.
30 |
31 | > **Note**: `--timeout` is currently not working on macOS. See .
32 |
33 | In some cases bisecting if a timeout happens is not enough, there might also be a compilation error (see for example [rustc#139197](https://github.com/rust-lang/rust/issues/139197)). In this case the script should handle all the work, here's a Bash example (given `main.rs` is the Rust code to reproduce the hanging compilation):
34 | ```sh
35 | #!/bin/bash
36 | res=$( timeout 3 rustc main.rs )
37 | if [ "$?" -eq 124 ]; then
38 | # Excessive compile time
39 | exit 1
40 | else
41 | # Compilation fails as expected *but* it doesn't hang
42 | exit 0
43 | fi
44 | ```
45 |
46 | and then run (example):
47 | ```sh
48 | cargo-bisect-rustc [...params...] --script test.sh
49 | ```
50 |
--------------------------------------------------------------------------------
/guide/src/examples/windows-scripting.md:
--------------------------------------------------------------------------------
1 | # Scripting on Windows
2 |
3 | Using the `--script` option on Windows can be cumbersome because Windows does not support `#!` scripts like Unix does, and the built-in scripting can also be awkward.
4 | The following sections show the different ways you can use scripting.
5 |
6 | ## Batch file
7 |
8 | You can use DOS-style `.bat` files:
9 |
10 | `test.bat`:
11 | ```bat
12 | (cargo check 2>&1) | find "E0642"
13 | ```
14 |
15 | This can be executed directly with:
16 |
17 | ```sh
18 | cargo-bisect-rustc --script ./test.bat
19 | ```
20 |
21 | But `.bat` can be challenging to do more complex options, or you may not be familiar with it.
22 |
23 | ## Powershell
24 |
25 | You can't execute `.ps1` Powershell files directly, so you will need to use `pwsh` to launch them:
26 |
27 | `test.ps1`:
28 | ```powershell
29 | ( cargo check 2>&1 ) | grep E0642
30 | if ( -Not $? ) {
31 | exit 1
32 | }
33 | ```
34 |
35 | This can be run with:
36 |
37 | ```sh
38 | cargo-bisect-rustc --script pwsh -- -File ./test.ps1
39 | ```
40 |
41 | ## Bash
42 |
43 | If you have Git-for-Windows installed, then you can use its copy of bash to run bash scripts:
44 |
45 | `test.sh`:
46 | ```sh
47 | #!/bin/bash
48 |
49 | cargo check 2>&1 | grep E0642
50 | ```
51 |
52 | This can be run with:
53 |
54 | ```sh
55 | cargo-bisect-rustc --script "C:\\Program Files\\Git\\usr\\bin\\bash.exe" -- ./test.sh
56 | ```
57 |
58 | This also works if you have bash from something like msys2 installed.
59 |
--------------------------------------------------------------------------------
/guide/src/examples/without-cargo.md:
--------------------------------------------------------------------------------
1 | # Running without cargo
2 |
3 | Some bisections don't require Cargo.
4 | You can use the `--without-cargo` option to skip installing cargo which can speed up the bisection since it doesn't need to download cargo, and doesn't have the overhead of running cargo.
5 | You will need to pair this with `--script` since `cargo-bisect-rustc` assumes projects use Cargo.
6 |
7 | For example, using a simple `rustc` command:
8 |
9 | ```sh
10 | cargo-bisect-rustc --start=2022-11-01 --end=2022-11-20 --without-cargo --script=rustc -- foo.rs
11 | ```
12 |
13 | > **Note**: You can use `--without-cargo` while still using a Cargo project.
14 | > Rustup will fall back to using `cargo` from your installed nightly, beta, or stable toolchain.
15 | > However, this isn't recommended since `cargo` is only intended to work with the version it is released with, and can sometimes be incompatible with different versions.
16 | > But if you are bisecting a very recent change, then you can probably get away with it.
17 |
--------------------------------------------------------------------------------
/guide/src/git-bisect.md:
--------------------------------------------------------------------------------
1 | # Git bisect a custom build
2 |
3 | There are some rare cases where you may need to build `rustc` with custom options, or otherwise work around issues with pre-built compilers not being available.
4 | For this you can use [`git bisect`] to build the compiler locally.
5 |
6 | It can be helpful to use the `--first-parent` option so that it only bisects the merge commits directly reachable on the master branch.
7 | Otherwise the bisecting may land on intermediate commits from within a PR which may not build or test correctly.
8 |
9 | To start the bisection, specifying the boundaries where the bisection will start:
10 |
11 | ```sh
12 | git bisect start --first-parent
13 | git bisect good 96ddd32c4bfb1d78f0cd03eb068b1710a8cebeef
14 | git bisect bad a00f8ba7fcac1b27341679c51bf5a3271fa82df3
15 | ```
16 |
17 | Then, build the compiler as needed and run your tests to check for a regression:
18 |
19 | ```sh
20 | ./x.py build std
21 | rustc +stage1 foo.rs
22 | ```
23 |
24 | You may want to consider running `./x.py clean` if you are running into issues since changes to the internal structures of build artifacts aren't always versioned, and those changes can be incompatible.
25 | Incremental caches are particularly susceptible, so you may want to turn that off if you have turned them on.
26 |
27 | If you determine the current version is good or bad, run `git bisect good` or `git bisect bad` to mark that, and then repeat building and marking until finished.
28 |
29 | Similar to `cargo-bisect-rustc`, `git bisect` supports scripting and lots of other goodies.
30 | Check out its documentation for more.
31 |
32 | [`git bisect`]: https://git-scm.com/docs/git-bisect
33 |
--------------------------------------------------------------------------------
/guide/src/installation.md:
--------------------------------------------------------------------------------
1 | # Installation
2 |
3 | The basic method for installing `cargo-bisect-rustc` is:
4 |
5 | ```sh
6 | cargo install cargo-bisect-rustc
7 | ```
8 |
9 | Additional options are described below.
10 |
11 | ## Requirements
12 |
13 | Besides having a working Rust installation, you may need a few other things installed on your system:
14 |
15 | - Unix:
16 | - pkg-config
17 | - OpenSSL (`libssl-dev` on Ubuntu, `openssl-devel` on Fedora or Alpine)
18 | - macOS:
19 | - OpenSSL ([homebrew] is recommended to install the `openssl` package)
20 | - [rustup]
21 |
22 | [homebrew]: https://brew.sh/
23 | [rustup]: https://rustup.rs/
24 |
25 | If you're having trouble using the system OpenSSL installation, it can be built from scratch.
26 | The following will enable the vendored OpenSSL build:
27 |
28 | ```sh
29 | cargo install cargo-bisect-rustc --features git2/vendored-openssl
30 | ```
31 |
32 | Beware that this also requires `perl` and `make` to be installed.
33 |
34 | ## `RUST_SRC_REPO`
35 |
36 | `cargo-bisect-rustc` needs to access the git log of the rust repo.
37 | You can set the default location of that when installing it:
38 |
39 | ```sh
40 | RUST_SRC_REPO=/path/to/rust cargo install cargo-bisect-rustc
41 | ```
42 |
43 | See [Rust source repo] for more about configuring how `cargo-bisect-rustc` retrieves this information.
44 |
45 | [Rust source repo]: rust-src-repo.md
46 |
--------------------------------------------------------------------------------
/guide/src/introduction.md:
--------------------------------------------------------------------------------
1 | # Introduction
2 |
3 | The [`cargo-bisect-rustc`] tool makes it super easy to find exactly when behavior has regressed in rustc.
4 | It automatically downloads rustc artifacts and tests them against a project you provide until it finds the regression.
5 |
6 | The [Installation](installation.md) chapter shows how to install `cargo-bisect-rustc`.
7 | For a quick introduction, see the [Tutorial](tutorial.md).
8 | Otherwise, start at the [Basic usage](usage.md) chapter to learn how `cargo-bisect-rustc` works.
9 |
10 | [`cargo-bisect-rustc`]: https://github.com/rust-lang/cargo-bisect-rustc
11 |
--------------------------------------------------------------------------------
/guide/src/rust-src-repo.md:
--------------------------------------------------------------------------------
1 | # Rust source repo
2 |
3 | For `cargo-bisect-rustc` to work, it needs to be able to read the git log of the [`rust-lang/rust`] repo.
4 | `cargo-bisect-rustc` supports several methods for this described below.
5 |
6 | ## GitHub API
7 |
8 | By default, `cargo-bisect-rustc` uses the GitHub API to fetch the information instead of using a local checkout.
9 |
10 | ```sh
11 | cargo bisect-rustc --access=github
12 | ```
13 |
14 | Beware that GitHub has restrictive rate limits for unauthenticated requests.
15 | It allows 60 requests per hour, and `cargo-bisect-rustc` will use about 10 requests each time you run it (which can vary depending on the bisection).
16 | If you run into the rate limit, you can raise it to 5000 requests per hour by setting the `GITHUB_TOKEN` environment variable to a [GitHub personal token].
17 | If you use the [`gh` CLI tool], you can use it to get a token:
18 |
19 | ```sh
20 | GITHUB_TOKEN=`gh auth token` cargo bisect-rustc --access=github
21 | ```
22 |
23 | If you don't use `gh`, you'll just need to copy and paste the token.
24 |
25 | ## Local clone
26 |
27 | `cargo-bisect-rustc` can also clone the rust repo in the current directory (as `rust.git`).
28 | This option can be quite slow if you don't specify the repo path at build time.
29 | You can specify this with the `--access` CLI argument:
30 | ```sh
31 | cargo bisect-rustc --access=checkout
32 | ```
33 |
34 | ## `RUST_SRC_REPO` environment variable
35 |
36 | You can specify the location of the rust repo with the `RUST_SRC_REPO` environment variable at runtime.
37 | This is useful if you already have it checked out somewhere, but is cumbersome to use.
38 |
39 | ```sh
40 | RUST_SRC_REPO=/path/to/rust cargo bisect-rustc
41 | ```
42 |
43 | ## `RUST_SRC_REPO` environment variable (build-time)
44 |
45 | Setting the `RUST_SRC_REPO` environment variable when installing `cargo-bisect-rustc` will set the default location for the rust repo.
46 | This is recommended if you already have the rust repo checked out somewhere.
47 |
48 | ```sh
49 | RUST_SRC_REPO=/path/to/rust cargo install cargo-bisect-rustc
50 | ```
51 |
52 | [`rust-lang/rust`]: https://github.com/rust-lang/rust/
53 | [GitHub personal token]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token
54 | [`gh` CLI tool]: https://cli.github.com/
55 |
--------------------------------------------------------------------------------
/guide/src/rustup.md:
--------------------------------------------------------------------------------
1 | # Rustup toolchains
2 |
3 | `cargo-bisect-rustc` takes advantage of [rustup toolchains] for installation and selecting the correct `rustc` to run.
4 | It will essentially run `cargo +bisector-nightly-2023-03-18-x86_64-unknown-linux-gnu build` using rustup [toolchain override shorthand] to run the toolchains that it downloads.
5 | This sets the `RUSTUP_TOOLCHAIN` environment variable to the toolchain name, which ensures that any call to `rustc` will use the correct toolchain.
6 |
7 | By default, `cargo-bisect-rustc` will delete toolchains immediately after using them.
8 | You can use the `--preserve` option to keep the toolchains so that you can use them manually.
9 | See the [Preserving toolchains] example for more details.
10 |
11 | When using the `--script` option, the script should just invoke `cargo` or `rustc` normally, and rely on the `RUSTUP_TOOLCHAIN` environment variable to pick the correct toolchain.
12 |
13 | [rustup toolchains]: https://rust-lang.github.io/rustup/concepts/toolchains.html
14 | [toolchain override shorthand]: https://rust-lang.github.io/rustup/overrides.html#toolchain-override-shorthand
15 | [Preserving toolchains]: examples/preserve.md
16 |
--------------------------------------------------------------------------------
/guide/src/tutorial.md:
--------------------------------------------------------------------------------
1 | # Tutorial
2 |
3 | `cargo-bisect-rustc` works by building a Cargo project and checking if it succeeds or fails.
4 | This tutorial walks through an example of this process.
5 |
6 | ## Finding a regression
7 |
8 | Create a cargo project that demonstrates the regression.
9 | Let's use [issue #53157] as an example:
10 |
11 | ```sh
12 | cargo new foo
13 | cd foo
14 | ```
15 |
16 | Edit `src/main.rs` with the example from the issue:
17 |
18 | ```rust
19 | macro_rules! m {
20 | () => {{
21 | fn f(_: impl Sized) {}
22 | f
23 | }}
24 | }
25 |
26 | fn main() {
27 | fn f() -> impl Sized {};
28 | m!()(f());
29 | }
30 | ```
31 |
32 | Since we are testing an old regression, also edit `Cargo.toml` to remove the `edition = "2021"` field which isn't supported in these versions.
33 |
34 | Then run `cargo bisect-rustc --end=2018-08-04`.
35 |
36 | We need to provide the end point for this particular example because that's an old regression already fixed on the latest nightlies.
37 | We could also provide a start point if we know one;
38 | that's going to make it faster by avoiding scanning for the start.
39 | For instance:
40 |
41 | ```sh
42 | cargo bisect-rustc --start=2018-05-07 --end=2018-08-04
43 | ```
44 |
45 | It will run `cargo build` in the project and check whether or not it fails.
46 | It will do a binary search between the start and end range to find exactly where the regression occurred.
47 |
48 | > **Note**: You can also use the flag [`--regress`] to specify other common regression criteria, e.g. `--regress=ice` for internal compiler errors.
49 |
50 | [`--regress`]: usage.md#regression-check
51 |
52 | In our example, in just a few steps, we can we find that it stopped working on `nightly-2018-07-30`.
53 |
54 | If the regression is recent enough, then it will print out a list of PRs that were committed on that date.
55 | In this particular example, it is too old, so we'll need to manually inspect the git log to see which PR's were merged.
56 |
57 | If the nightly was within the last 167 days, then `cargo-bisect-rustc` will then start bisecting those individual PRs.
58 |
59 | After finding potential candidates, you can go inspect those PRs to see which one is the likely cause.
60 | In this case, since the ICE was in MIR const propagation, and #51361 is the likely candidate since it modified const evaluation.
61 |
62 | ## Testing interactively
63 |
64 | Pass/fail of `cargo build` may not be what you're after.
65 | Perhaps the issue is an error message changed, so both the "good" and "bad" version will fail to
66 | compile, just with a different message.
67 | Or maybe something used to fail, and now erroneously passes.
68 | You can use the interactive feature with the `--prompt` flag to visually inspect a build and tell `cargo-bisect-rustc` what's "good" and what's "bad".
69 | Let's use [issue #55036] as an example where an error message changed:
70 |
71 | In `Cargo.toml`, remove the `edition` field (this example was before editions).
72 |
73 | `src/main.rs`:
74 | ```rust
75 | struct Foo {
76 | bar: i32
77 | }
78 |
79 | trait Baz {
80 | fn f(Foo { bar }: Foo) {}
81 | }
82 |
83 | fn main() {}
84 | ```
85 |
86 | This historically emitted a bad error, was updated to emit a nice error (E0642 added in #53051), but then that nice error was lost somewhere (on the 2015 edition).
87 | Let's find where it was lost!
88 | Grab the ranges between where it was added and where we know it fails:
89 |
90 | ```sh
91 | cargo bisect-rustc --prompt \
92 | --start=2018-08-14 \
93 | --end=2018-10-11
94 | ```
95 |
96 | At each step, `cargo-bisect-rustc` will show the output and ask you:
97 |
98 | ```text
99 | nightly-2018-08-14 finished with exit code Some(101).
100 | please select an action to take:
101 | > mark regressed
102 | mark baseline
103 | retry
104 | ```
105 |
106 | Choose `mark baseline` with the nice E0642 message, and `mark regressed` with the less-favorable token error.
107 | Fairly quickly we find it regressed in nightly-2018-10-11.
108 | The most likely candidate is #54457 which is a rollup PR.
109 | It's usually not too hard to look through the commits and find a likely culprit.
110 | Indeed in this example, #54415 modified function parameter parsing.
111 |
112 | ## Testing with a script
113 |
114 | Using the `--script` option allows you to do something more fancy than just `cargo build`.
115 | Maybe you need to run cargo multiple times, or just call `rustc` directly, or you want to automatically grep through the output.
116 | The possibilities are endless!
117 | Just write a little shell script that exits 0 for the baseline, and exits nonzero for the regression.
118 | As an example, the previous interactive session can be hands-free automated with this script:
119 |
120 | `test.sh`:
121 | ```sh
122 | #!/bin/sh
123 |
124 | # Fail if we no longer get a `E0642` error:
125 | cargo check 2>&1 | grep E0642
126 | ```
127 |
128 | And then run:
129 |
130 | ```sh
131 | cargo bisect-rustc --script=./test.sh \
132 | --start=2018-08-14 \
133 | --end=2018-10-11
134 | ```
135 |
136 | [issue #53157]: https://github.com/rust-lang/rust/issues/53157
137 | [issue #55036]: https://github.com/rust-lang/rust/issues/55036
138 |
139 | ## Custom bisection messages
140 |
141 | *Available from v0.6.9*
142 |
143 | You can add custom messages when bisecting a regression. Taking inspiration from git-bisect, with `term-new` and `term-old` you can set custom messages to indicate if a regression matches the condition set by the bisection.
144 |
145 | Example:
146 | ```sh
147 | cargo bisect-rustc \
148 | --start=2018-08-14 \
149 | --end=2018-10-11 \
150 | --term-old "No, this build did not reproduce the regression, compile successful" \
151 | --term-new "Yes, this build reproduces the regression, compile error"
152 | ```
153 |
154 | In other words, `--term-old` is displayed for older compilers that **do not** exhibit the regression. `--term-new` is for newer compilers which do exhibit the regression.
155 |
156 | What counts as a "regression" is defined by the [`--regress`](usage.html#regression-check) CLI option. By default, a regression is a compile-error (which is equivalent to `--term-new`). If you flip the definition of a "regression" with `--regress=success`, then a regression is a successful compile (which is *also* equivalent to `--term-new`).
157 |
158 | There are default terms based on the current `--regress` setting. Customizing the terms is most useful when using [scripting](#testing-with-a-script). For example, in the [Documentation changes](examples/doc-change.md) example, the customized terms can more clearly express the results of the script of whether or not it found what it was looking for in the documentation.
159 |
--------------------------------------------------------------------------------
/guide/src/usage.md:
--------------------------------------------------------------------------------
1 | # Basic usage
2 |
3 | Using `cargo-bisect-rustc` simply involves running it inside a Cargo project that reproduces the regression:
4 |
5 | ```sh
6 | cargo bisect-rustc
7 | ```
8 |
9 | > For a quick introduction, see the [Tutorial](tutorial.md).
10 |
11 | `cargo-bisect-rustc` works by building a Cargo project, and detecting if it succeeds or fails.
12 | It will download and use nightly Rust toolchains.
13 | It begins with two nightly boundaries, known as the *start* where the project successfully builds (the *baseline*), and the *end* where it is known to fail (the *regression*).
14 | It will then do a binary search between those dates to find the nightly where the project started to fail.
15 |
16 | Once it finds the nightly where it started to fail, `cargo-bisect-rustc` will then try to find the individual PR where it regressed.
17 | The Rust project keeps the builds of every merged PR for the last 167 days.
18 | If the nightly is within that range, then it will bisect between those PRs.
19 |
20 | And even further, if the regression is in a [rollup PR], then it will bisect the individual PRs within the rollup.
21 | This final bisection is only available for `x86_64-unknown-linux-gnu` since it is using the builds made for the [rustc performance tracker].
22 |
23 | [rollup PR]: https://forge.rust-lang.org/release/rollups.html
24 | [rustc performance tracker]: https://perf.rust-lang.org/
25 |
26 | ## Rust src repo
27 |
28 | `cargo-bisect-rustc` needs to read the git log of the [`rust-lang/rust`] repo in order to scan individual commits.
29 | See the [Rust src repo] chapter for details on how to configure how it finds the git repo.
30 |
31 | [Rust src repo]: rust-src-repo.md
32 | [`rust-lang/rust`]: https://github.com/rust-lang/rust/
33 |
34 | ## Boundaries
35 |
36 | Without setting any options, `cargo-bisect-rustc` will try to automatically find the *start* where the build succeeds and the *end* where it fails.
37 | This can take some time, depending on how far back it needs to scan.
38 | It is recommended to use the `--start` and `--end` CLI options to tell it where the boundaries are.
39 |
40 | ```sh
41 | cargo bisect-rustc --start=2022-11-01 --end=2023-02-14
42 | ```
43 |
44 | See the [Bisection boundaries] chapter for more details on setting these options.
45 |
46 | [Bisection boundaries]: boundaries.md
47 |
48 | ## Regression check
49 |
50 | By default, `cargo-bisect-rustc` assumes the *start* boundary successfully builds, and the *end* boundary fails to build.
51 | You can change this using the `--regress` CLI option.
52 | For example, you can tell it that the *start* should fail, and the *end* should pass.
53 | There are several options you can use with the `--regress` flag:
54 |
55 |
60 |
61 | | Option | Start | End | Description |
62 | |--------|-------|-----|-------------|
63 | | `error` | Succeed | Fail | The default setting checks for a failure as the regression. |
64 | | `success` | Fail | Succeed | Reverses the check to find when something is *fixed*. |
65 | | `ice` | No ICE | ICE | Scans when an Internal Compiler Error (ICE) was introduced. |
66 | | `non-ice` | ICE | No ICE | Scans when an ICE was fixed. |
67 | | `non-error` | Non-ICE Failure | Succeed or ICE | Scans when an ill-formed program stops being properly rejected, or the compiler starts generating an ICE. |
68 |
69 | See [Scripting](#scripting) for customizing this behavior.
70 |
71 | ## Custom commands
72 |
73 | By default, `cargo-bisect-rustc` runs `cargo build`.
74 | You can change which `cargo` command is run by passing additional arguments after `--`:
75 |
76 | ```sh
77 | cargo bisect-rustc -- test --test mytest
78 | ```
79 |
80 | ## Scripting
81 |
82 | You can use an arbitrary script for determining what is a baseline and regression.
83 | This is an extremely flexible option that allows you to perform any action automatically.
84 | Just pass the path to the script to the `--script` CLI command:
85 |
86 | ```sh
87 | cargo bisect-rustc --script ./test.sh
88 | ```
89 |
90 | The script should exit 0 for the baseline, and nonzero for a regression.
91 | Since `cargo-bisect-rustc` sets `RUSTUP_TOOLCHAIN` (see [Rustup toolchains](rustup.md)), all you need to do is call `cargo` or `rustc`, and the script should automatically use the toolchain that is currently being tested.
92 |
93 | ```sh
94 | #!/bin/sh
95 |
96 | set -ex
97 |
98 | # This checks that a warning is only printed once.
99 | # See https://github.com/rust-lang/rust/issues/88256 for a regression where it
100 | # started printing twice.
101 |
102 | OUTPUT=`cargo check 2>&1`
103 | COUNT=`echo "$OUTPUT" | grep -c "unnecessary parentheses"`
104 | test $COUNT -eq 1
105 | ```
106 |
107 | If you need to use the targets directly without using `cargo` in the script, they are available in `$CARGO_TARGET_DIR/[release|debug]/...`, since `cargo-bisect-rustc` sets `$CARGO_TARGET_DIR`.
108 |
109 | Check out the [examples chapters](examples/index.md) for several examples of how to use this option.
110 |
--------------------------------------------------------------------------------
/src/bounds.rs:
--------------------------------------------------------------------------------
1 | //! Definitions of bisection bounds.
2 |
3 | use crate::toolchains::{
4 | download_progress, parse_to_naive_date, Toolchain, NIGHTLY_SERVER, YYYY_MM_DD,
5 | };
6 | use crate::GitDate;
7 | use crate::Opts;
8 | use crate::{today, EPOCH_COMMIT};
9 | use anyhow::bail;
10 | use chrono::NaiveDate;
11 | use reqwest::blocking::Client;
12 | use std::io::Read;
13 | use std::str::FromStr;
14 |
15 | /// A bisection boundary.
16 | #[derive(Clone, Debug)]
17 | pub enum Bound {
18 | Commit(String),
19 | Date(GitDate),
20 | }
21 |
22 | impl FromStr for Bound {
23 | type Err = std::convert::Infallible;
24 | fn from_str(s: &str) -> Result {
25 | parse_to_naive_date(s)
26 | .map(Self::Date)
27 | .or_else(|_| Ok(Self::Commit(s.to_string())))
28 | }
29 | }
30 |
31 | impl Bound {
32 | /// Returns the SHA of this boundary.
33 | ///
34 | /// For nightlies, this will fetch from the network.
35 | pub fn sha(&self) -> anyhow::Result {
36 | match self {
37 | Bound::Commit(commit) => Ok(commit.clone()),
38 | Bound::Date(date) => {
39 | let date_str = date.format(YYYY_MM_DD);
40 | let url =
41 | format!("{NIGHTLY_SERVER}/{date_str}/channel-rust-nightly-git-commit-hash.txt");
42 |
43 | eprintln!("fetching {url}");
44 | let client = Client::new();
45 | let name = format!("nightly manifest {date_str}");
46 | let mut response = download_progress(&client, &name, &url)?;
47 | let mut commit = String::new();
48 | response.read_to_string(&mut commit)?;
49 |
50 | eprintln!("converted {date_str} to {commit}");
51 |
52 | Ok(commit)
53 | }
54 | }
55 | }
56 | }
57 |
58 | /// The starting bisection bounds.
59 | pub enum Bounds {
60 | /// Indicates to search backwards from the given date to find the start
61 | /// date where the regression does not occur.
62 | SearchNightlyBackwards { end: GitDate },
63 | /// Search between two commits.
64 | ///
65 | /// `start` and `end` must be SHA1 hashes of the commit object.
66 | Commits { start: String, end: String },
67 | /// Search between two dates.
68 | Dates { start: GitDate, end: GitDate },
69 | }
70 |
71 | impl Bounds {
72 | pub fn from_args(args: &Opts) -> anyhow::Result {
73 | let (start, end) = translate_tags(&args)?;
74 | let today = today();
75 | let check_in_future = |which, date: &NaiveDate| -> anyhow::Result<()> {
76 | if date > &today {
77 | bail!(
78 | "{which} date should be on or before current date, \
79 | got {which} date request: {date} and current date is {today}"
80 | );
81 | }
82 | Ok(())
83 | };
84 | let bounds = match (start, end) {
85 | // Neither --start or --end specified.
86 | (None, None) => Bounds::SearchNightlyBackwards {
87 | end: installed_nightly_or_latest()?,
88 | },
89 |
90 | // --start or --end is a commit
91 | (Some(Bound::Commit(start)), Some(Bound::Commit(end))) => {
92 | Bounds::Commits { start, end }
93 | }
94 | (Some(Bound::Commit(start)), None) => Bounds::Commits {
95 | start,
96 | end: args.access.repo().commit("origin/master")?.sha,
97 | },
98 | (None, Some(Bound::Commit(end))) => Bounds::Commits {
99 | start: EPOCH_COMMIT.to_string(),
100 | end,
101 | },
102 |
103 | // --start or --end is a date
104 | (Some(Bound::Date(start)), Some(Bound::Date(end))) => {
105 | check_in_future("start", &start)?;
106 | check_in_future("end", &end)?;
107 | Bounds::Dates { start, end }
108 | }
109 | (Some(Bound::Date(start)), None) => {
110 | check_in_future("start", &start)?;
111 | Bounds::Dates {
112 | start,
113 | end: find_latest_nightly()?,
114 | }
115 | }
116 | (None, Some(Bound::Date(end))) => {
117 | check_in_future("end", &end)?;
118 | if args.by_commit {
119 | bail!("--by-commit with an end date requires --start to be specified");
120 | }
121 | Bounds::SearchNightlyBackwards { end }
122 | }
123 |
124 | // Mixed not supported.
125 | (Some(Bound::Commit(_)), Some(Bound::Date(_)))
126 | | (Some(Bound::Date(_)), Some(Bound::Commit(_))) => bail!(
127 | "cannot take different types of bounds for start/end, \
128 | got start: {:?} and end {:?}",
129 | args.start,
130 | args.end
131 | ),
132 | };
133 | if let Bounds::Dates { start, end } = &bounds {
134 | if end < start {
135 | bail!("end should be after start, got start: {start} and end {end}");
136 | }
137 | if args.by_commit {
138 | eprintln!("finding commit range that corresponds to dates specified");
139 | let bounds = Bounds::Commits {
140 | start: date_to_sha(&start)?,
141 | end: date_to_sha(&end)?,
142 | };
143 | return Ok(bounds);
144 | }
145 | }
146 | Ok(bounds)
147 | }
148 | }
149 |
150 | /// Translates a tag-like bound (such as `1.62.0`) to a `Bound::Date` so that
151 | /// bisecting works for versions older than 167 days.
152 | fn translate_tags(args: &Opts) -> anyhow::Result<(Option, Option)> {
153 | let is_tag = |bound: &Option| -> bool {
154 | match bound {
155 | Some(Bound::Commit(commit)) => commit.contains('.'),
156 | None | Some(Bound::Date(_)) => false,
157 | }
158 | };
159 | let is_datelike = |bound: &Option| -> bool {
160 | matches!(bound, None | Some(Bound::Date(_))) || is_tag(bound)
161 | };
162 | if !(is_datelike(&args.start) && is_datelike(&args.end)) {
163 | // If the user specified an actual commit for one bound, then don't
164 | // even try to convert the other bound to a date.
165 | return Ok((args.start.clone(), args.end.clone()));
166 | }
167 | let fixup = |which: &str, bound: &Option| -> anyhow::Result