]> git.proxmox.com Git - rustc.git/blob - src/doc/rustc-dev-guide/src/compiler-debugging.md
New upstream version 1.65.0+dfsg1
[rustc.git] / src / doc / rustc-dev-guide / src / compiler-debugging.md
1 # Debugging the compiler
2 [debugging]: #debugging
3
4 <!-- toc -->
5
6 This chapter contains a few tips to debug the compiler. These tips aim to be
7 useful no matter what you are working on. Some of the other chapters have
8 advice about specific parts of the compiler (e.g. the [Queries Debugging and
9 Testing chapter](./incrcomp-debugging.html) or the [LLVM Debugging
10 chapter](./backend/debugging.md)).
11
12 ## Configuring the compiler
13
14 By default, rustc is built without most debug information. To enable debug info,
15 set `debug = true` in your config.toml.
16
17 Setting `debug = true` turns on many different debug options (e.g., `debug-assertions`,
18 `debug-logging`, etc.) which can be individually tweaked if you want to, but many people
19 simply set `debug = true`.
20
21 If you want to use GDB to debug rustc, please set `config.toml` with options:
22
23 ```toml
24 [rust]
25 debug = true
26 debuginfo-level = 2
27 ```
28
29 > NOTE:
30 > This will use a lot of disk space
31 > (upwards of <!-- date-check Aug 2022 --> 35GB),
32 > and will take a lot more compile time.
33 > With `debuginfo-level = 1` (the default when `debug = true`),
34 > you will be able to track the execution path,
35 > but will lose the symbol information for debugging.
36
37 The default configuration will enable `symbol-mangling-version` v0.
38 This requires at least GDB v10.2,
39 otherwise you need to disable new symbol-mangling-version in `config.toml`.
40
41 ```toml
42 [rust]
43 new-symbol-mangling = false
44 ```
45
46 > See the comments in `config.toml.example` for more info.
47
48 You will need to rebuild the compiler after changing any configuration option.
49
50 ## `-Z` flags
51
52 The compiler has a bunch of `-Z` flags. These are unstable flags that are only
53 enabled on nightly. Many of them are useful for debugging. To get a full listing
54 of `-Z` flags, use `-Z help`.
55
56 One useful flag is `-Z verbose`, which generally enables printing more info that
57 could be useful for debugging.
58
59 ## Getting a backtrace
60 [getting-a-backtrace]: #getting-a-backtrace
61
62 When you have an ICE (panic in the compiler), you can set
63 `RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in
64 normal Rust programs. IIRC backtraces **don't work** on MinGW,
65 sorry. If you have trouble or the backtraces are full of `unknown`,
66 you might want to find some way to use Linux, Mac, or MSVC on Windows.
67
68 In the default configuration (without `debug` set to `true`), you don't have line numbers
69 enabled, so the backtrace looks like this:
70
71 ```text
72 stack backtrace:
73 0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
74 1: std::sys_common::backtrace::_print
75 2: std::panicking::default_hook::{{closure}}
76 3: std::panicking::default_hook
77 4: std::panicking::rust_panic_with_hook
78 5: std::panicking::begin_panic
79 (~~~~ LINES REMOVED BY ME FOR BREVITY ~~~~)
80 32: rustc_typeck::check_crate
81 33: <std::thread::local::LocalKey<T>>::with
82 34: <std::thread::local::LocalKey<T>>::with
83 35: rustc::ty::context::TyCtxt::create_and_enter
84 36: rustc_driver::driver::compile_input
85 37: rustc_driver::run_compiler
86 ```
87
88 If you set `debug = true`, you will get line numbers for the stack trace.
89 Then the backtrace will look like this:
90
91 ```text
92 stack backtrace:
93 (~~~~ LINES REMOVED BY ME FOR BREVITY ~~~~)
94 at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:110
95 7: rustc_typeck::check::cast::CastCheck::check
96 at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:572
97 at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:460
98 at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:370
99 (~~~~ LINES REMOVED BY ME FOR BREVITY ~~~~)
100 33: rustc_driver::driver::compile_input
101 at /home/user/rust/compiler/rustc_driver/src/driver.rs:1010
102 at /home/user/rust/compiler/rustc_driver/src/driver.rs:212
103 34: rustc_driver::run_compiler
104 at /home/user/rust/compiler/rustc_driver/src/lib.rs:253
105 ```
106
107 ## Getting a backtrace for errors
108 [getting-a-backtrace-for-errors]: #getting-a-backtrace-for-errors
109
110 If you want to get a backtrace to the point where the compiler emits an
111 error message, you can pass the `-Z treat-err-as-bug=n`, which will make
112 the compiler panic on the `nth` error on `delay_span_bug`. If you leave
113 off `=n`, the compiler will assume `1` for `n` and thus panic on the
114 first error it encounters.
115
116 This can also help when debugging `delay_span_bug` calls - it will make
117 the first `delay_span_bug` call panic, which will give you a useful backtrace.
118
119 For example:
120
121 ```bash
122 $ cat error.rs
123 ```
124
125 ```rust
126 fn main() {
127 1 + ();
128 }
129 ```
130
131 ```bash
132 $ rustc +stage1 error.rs
133 error[E0277]: cannot add `()` to `{integer}`
134 --> error.rs:2:7
135 |
136 2 | 1 + ();
137 | ^ no implementation for `{integer} + ()`
138 |
139 = help: the trait `Add<()>` is not implemented for `{integer}`
140
141 error: aborting due to previous error
142 ```
143
144 Now, where does the error above come from?
145
146 ```bash
147 $ RUST_BACKTRACE=1 rustc +stage1 error.rs -Z treat-err-as-bug
148 error[E0277]: the trait bound `{integer}: std::ops::Add<()>` is not satisfied
149 --> error.rs:2:7
150 |
151 2 | 1 + ();
152 | ^ no implementation for `{integer} + ()`
153 |
154 = help: the trait `std::ops::Add<()>` is not implemented for `{integer}`
155
156 error: internal compiler error: unexpected panic
157
158 note: the compiler unexpectedly panicked. this is a bug.
159
160 note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports
161
162 note: rustc 1.24.0-dev running on x86_64-unknown-linux-gnu
163
164 note: run with `RUST_BACKTRACE=1` for a backtrace
165
166 thread 'rustc' panicked at 'encountered error with `-Z treat_err_as_bug',
167 /home/user/rust/compiler/rustc_errors/src/lib.rs:411:12
168 note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose
169 backtrace.
170 stack backtrace:
171 (~~~ IRRELEVANT PART OF BACKTRACE REMOVED BY ME ~~~)
172 7: rustc::traits::error_reporting::<impl rustc::infer::InferCtxt<'a, 'tcx>>
173 ::report_selection_error
174 at /home/user/rust/compiler/rustc_middle/src/traits/error_reporting.rs:823
175 8: rustc::traits::error_reporting::<impl rustc::infer::InferCtxt<'a, 'tcx>>
176 ::report_fulfillment_errors
177 at /home/user/rust/compiler/rustc_middle/src/traits/error_reporting.rs:160
178 at /home/user/rust/compiler/rustc_middle/src/traits/error_reporting.rs:112
179 9: rustc_typeck::check::FnCtxt::select_obligations_where_possible
180 at /home/user/rust/compiler/rustc_typeck/src/check/mod.rs:2192
181 (~~~ IRRELEVANT PART OF BACKTRACE REMOVED BY ME ~~~)
182 36: rustc_driver::run_compiler
183 at /home/user/rust/compiler/rustc_driver/src/lib.rs:253
184 ```
185
186 Cool, now I have a backtrace for the error!
187
188 ## Getting logging output
189
190 The compiler uses the [`tracing`] crate for logging.
191
192 [`tracing`]: https://docs.rs/tracing
193
194 For details see [the guide section on tracing](./tracing.md)
195
196 ## Formatting Graphviz output (.dot files)
197 [formatting-graphviz-output]: #formatting-graphviz-output
198
199 Some compiler options for debugging specific features yield graphviz graphs -
200 e.g. the `#[rustc_mir(borrowck_graphviz_postflow="suffix.dot")]` attribute
201 dumps various borrow-checker dataflow graphs.
202
203 These all produce `.dot` files. To view these files, install graphviz (e.g.
204 `apt-get install graphviz`) and then run the following commands:
205
206 ```bash
207 $ dot -T pdf maybe_init_suffix.dot > maybe_init_suffix.pdf
208 $ firefox maybe_init_suffix.pdf # Or your favorite pdf viewer
209 ```
210
211 ## Viewing Spanview output (.html files)
212 [viewing-spanview-output]: #viewing-spanview-output
213
214 In addition to [graphviz output](#formatting-graphviz-output-dot-files), MIR debugging
215 flags include an option to generate a MIR representation called `Spanview` that
216 uses HTML to highlight code regions in the original source code and display
217 compiler metadata associated with each region.
218 [`-Z dump-mir-spanview`](./mir/debugging.md), for example, highlights spans
219 associated with each MIR `Statement`, `Terminator`, and/or `BasicBlock`.
220
221 These `.html` files use CSS features to dynamically expand spans obscured by
222 overlapping spans, and native tooltips (based on the HTML `title` attribute) to
223 reveal the actual MIR elements, as text.
224
225 To view these files, simply use a modern browser, or a CSS-capable HTML preview
226 feature in a modern IDE. (The default HTML preview pane in *VS Code* is known to
227 work, for instance.)
228
229 ## Narrowing (Bisecting) Regressions
230
231 The [cargo-bisect-rustc][bisect] tool can be used as a quick and easy way to
232 find exactly which PR caused a change in `rustc` behavior. It automatically
233 downloads `rustc` PR artifacts and tests them against a project you provide
234 until it finds the regression. You can then look at the PR to get more context
235 on *why* it was changed. See [this tutorial][bisect-tutorial] on how to use
236 it.
237
238 [bisect]: https://github.com/rust-lang/cargo-bisect-rustc
239 [bisect-tutorial]: https://github.com/rust-lang/cargo-bisect-rustc/blob/master/TUTORIAL.md
240
241 ## Downloading Artifacts from Rust's CI
242
243 The [rustup-toolchain-install-master][rtim] tool by kennytm can be used to
244 download the artifacts produced by Rust's CI for a specific SHA1 -- this
245 basically corresponds to the successful landing of some PR -- and then sets
246 them up for your local use. This also works for artifacts produced by `@bors
247 try`. This is helpful when you want to examine the resulting build of a PR
248 without doing the build yourself.
249
250 [rtim]: https://github.com/kennytm/rustup-toolchain-install-master
251
252 ## Debugging type layouts
253
254 The (permanently) unstable `#[rustc_layout]` attribute can be used to dump
255 the [`Layout`] of the type it is attached to. For example:
256
257 ```rust
258 #![feature(rustc_attrs)]
259
260 #[rustc_layout(debug)]
261 type T<'a> = &'a u32;
262 ```
263
264 Will emit the following:
265
266 ```text
267 error: layout_of(&'a u32) = Layout {
268 fields: Primitive,
269 variants: Single {
270 index: 0,
271 },
272 abi: Scalar(
273 Scalar {
274 value: Pointer,
275 valid_range: 1..=18446744073709551615,
276 },
277 ),
278 largest_niche: Some(
279 Niche {
280 offset: Size {
281 raw: 0,
282 },
283 scalar: Scalar {
284 value: Pointer,
285 valid_range: 1..=18446744073709551615,
286 },
287 },
288 ),
289 align: AbiAndPrefAlign {
290 abi: Align {
291 pow2: 3,
292 },
293 pref: Align {
294 pow2: 3,
295 },
296 },
297 size: Size {
298 raw: 8,
299 },
300 }
301 --> src/lib.rs:4:1
302 |
303 4 | type T<'a> = &'a u32;
304 | ^^^^^^^^^^^^^^^^^^^^^
305
306 error: aborting due to previous error
307 ```
308
309 [`Layout`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/abi/struct.Layout.html