| # Debugging the compiler | 
 |  | 
 | <!-- toc --> | 
 |  | 
 | This chapter contains a few tips to debug the compiler. These tips aim to be | 
 | useful no matter what you are working on.  Some of the other chapters have | 
 | advice about specific parts of the compiler (e.g. the [Queries Debugging and | 
 | Testing chapter](./incrcomp-debugging.html) or the [LLVM Debugging | 
 | chapter](./backend/debugging.md)). | 
 |  | 
 | ## Configuring the compiler | 
 |  | 
 | By default, rustc is built without most debug information. To enable debug info, | 
 | set `debug = true` in your bootstrap.toml. | 
 |  | 
 | Setting `debug = true` turns on many different debug options (e.g., `debug-assertions`, | 
 | `debug-logging`, etc.) which can be individually tweaked if you want to, but many people | 
 | simply set `debug = true`. | 
 |  | 
 | If you want to use GDB to debug rustc, please set `bootstrap.toml` with options: | 
 |  | 
 | ```toml | 
 | [rust] | 
 | debug = true | 
 | debuginfo-level = 2 | 
 | ``` | 
 |  | 
 | > NOTE: | 
 | > This will use a lot of disk space | 
 | > (upwards of <!-- date-check Aug 2022 --> 35GB), | 
 | > and will take a lot more compile time. | 
 | > With `debuginfo-level = 1` (the default when `debug = true`), | 
 | > you will be able to track the execution path, | 
 | > but will lose the symbol information for debugging. | 
 |  | 
 | The default configuration will enable `symbol-mangling-version` v0. | 
 | This requires at least GDB v10.2, | 
 | otherwise you need to disable new symbol-mangling-version in `bootstrap.toml`. | 
 |  | 
 | ```toml | 
 | [rust] | 
 | new-symbol-mangling = false | 
 | ``` | 
 |  | 
 | > See the comments in `bootstrap.example.toml` for more info. | 
 |  | 
 | You will need to rebuild the compiler after changing any configuration option. | 
 |  | 
 | ## Suppressing the ICE file | 
 |  | 
 | By default, if rustc encounters an Internal Compiler Error (ICE) it will dump the ICE contents to an | 
 | ICE file within the current working directory named `rustc-ice-<timestamp>-<pid>.txt`. If this is | 
 | not desirable, you can prevent the ICE file from being created with `RUSTC_ICE=0`. | 
 |  | 
 | ## Getting a backtrace | 
 | [getting-a-backtrace]: #getting-a-backtrace | 
 |  | 
 | When you have an ICE (panic in the compiler), you can set | 
 | `RUST_BACKTRACE=1` to get the stack trace of the `panic!` like in | 
 | normal Rust programs. IIRC backtraces **don't work** on MinGW, | 
 | sorry. If you have trouble or the backtraces are full of `unknown`, | 
 | you might want to find some way to use Linux, Mac, or MSVC on Windows. | 
 |  | 
 | In the default configuration (without `debug` set to `true`), you don't have line numbers | 
 | enabled, so the backtrace looks like this: | 
 |  | 
 | ```text | 
 | stack backtrace: | 
 |    0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace | 
 |    1: std::sys_common::backtrace::_print | 
 |    2: std::panicking::default_hook::{{closure}} | 
 |    3: std::panicking::default_hook | 
 |    4: std::panicking::rust_panic_with_hook | 
 |    5: std::panicking::begin_panic | 
 |    (~~~~ LINES REMOVED BY ME FOR BREVITY ~~~~) | 
 |   32: rustc_typeck::check_crate | 
 |   33: <std::thread::local::LocalKey<T>>::with | 
 |   34: <std::thread::local::LocalKey<T>>::with | 
 |   35: rustc::ty::context::TyCtxt::create_and_enter | 
 |   36: rustc_driver::driver::compile_input | 
 |   37: rustc_driver::run_compiler | 
 | ``` | 
 |  | 
 | If you set `debug = true`, you will get line numbers for the stack trace. | 
 | Then the backtrace will look like this: | 
 |  | 
 | ```text | 
 | stack backtrace: | 
 |    (~~~~ LINES REMOVED BY ME FOR BREVITY ~~~~) | 
 |              at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:110 | 
 |    7: rustc_typeck::check::cast::CastCheck::check | 
 |              at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:572 | 
 |              at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:460 | 
 |              at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:370 | 
 |    (~~~~ LINES REMOVED BY ME FOR BREVITY ~~~~) | 
 |   33: rustc_driver::driver::compile_input | 
 |              at /home/user/rust/compiler/rustc_driver/src/driver.rs:1010 | 
 |              at /home/user/rust/compiler/rustc_driver/src/driver.rs:212 | 
 |   34: rustc_driver::run_compiler | 
 |              at /home/user/rust/compiler/rustc_driver/src/lib.rs:253 | 
 | ``` | 
 |  | 
 | ## `-Z` flags | 
 |  | 
 | The compiler has a bunch of `-Z *` flags. These are unstable flags that are only | 
 | enabled on nightly. Many of them are useful for debugging. To get a full listing | 
 | of `-Z` flags, use `-Z help`. | 
 |  | 
 | One useful flag is `-Z verbose-internals`, which generally enables printing more | 
 | info that could be useful for debugging. | 
 |  | 
 | Right below you can find elaborate explainers on a selected few. | 
 |  | 
 | ### Getting a backtrace for errors | 
 | [getting-a-backtrace-for-errors]: #getting-a-backtrace-for-errors | 
 |  | 
 | If you want to get a backtrace to the point where the compiler emits an | 
 | error message, you can pass the `-Z treat-err-as-bug=n`, which will make | 
 | the compiler panic on the `nth` error. If you leave off `=n`, the compiler will | 
 | assume `1` for `n` and thus panic on the first error it encounters. | 
 |  | 
 | For example: | 
 |  | 
 | ```bash | 
 | $ cat error.rs | 
 | ``` | 
 |  | 
 | ```rust | 
 | fn main() { | 
 |     1 + (); | 
 | } | 
 | ``` | 
 |  | 
 | ``` | 
 | $ rustc +stage1 error.rs | 
 | error[E0277]: cannot add `()` to `{integer}` | 
 |  --> error.rs:2:7 | 
 |   | | 
 | 2 |       1 + (); | 
 |   |         ^ no implementation for `{integer} + ()` | 
 |   | | 
 |   = help: the trait `Add<()>` is not implemented for `{integer}` | 
 |  | 
 | error: aborting due to previous error | 
 | ``` | 
 |  | 
 | Now, where does the error above come from? | 
 |  | 
 | ``` | 
 | $ RUST_BACKTRACE=1 rustc +stage1 error.rs -Z treat-err-as-bug | 
 | error[E0277]: the trait bound `{integer}: std::ops::Add<()>` is not satisfied | 
 |  --> error.rs:2:7 | 
 |   | | 
 | 2 |     1 + (); | 
 |   |       ^ no implementation for `{integer} + ()` | 
 |   | | 
 |   = help: the trait `std::ops::Add<()>` is not implemented for `{integer}` | 
 |  | 
 | error: internal compiler error: unexpected panic | 
 |  | 
 | note: the compiler unexpectedly panicked. this is a bug. | 
 |  | 
 | note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports | 
 |  | 
 | note: rustc 1.24.0-dev running on x86_64-unknown-linux-gnu | 
 |  | 
 | note: run with `RUST_BACKTRACE=1` for a backtrace | 
 |  | 
 | thread 'rustc' panicked at 'encountered error with `-Z treat_err_as_bug', | 
 | /home/user/rust/compiler/rustc_errors/src/lib.rs:411:12 | 
 | note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose | 
 | backtrace. | 
 | stack backtrace: | 
 |   (~~~ IRRELEVANT PART OF BACKTRACE REMOVED BY ME ~~~) | 
 |    7: rustc::traits::error_reporting::<impl rustc::infer::InferCtxt<'a, 'tcx>> | 
 |              ::report_selection_error | 
 |              at /home/user/rust/compiler/rustc_middle/src/traits/error_reporting.rs:823 | 
 |    8: rustc::traits::error_reporting::<impl rustc::infer::InferCtxt<'a, 'tcx>> | 
 |              ::report_fulfillment_errors | 
 |              at /home/user/rust/compiler/rustc_middle/src/traits/error_reporting.rs:160 | 
 |              at /home/user/rust/compiler/rustc_middle/src/traits/error_reporting.rs:112 | 
 |    9: rustc_typeck::check::FnCtxt::select_obligations_where_possible | 
 |              at /home/user/rust/compiler/rustc_typeck/src/check/mod.rs:2192 | 
 |   (~~~ IRRELEVANT PART OF BACKTRACE REMOVED BY ME ~~~) | 
 |   36: rustc_driver::run_compiler | 
 |              at /home/user/rust/compiler/rustc_driver/src/lib.rs:253 | 
 | ``` | 
 |  | 
 | Cool, now I have a backtrace for the error! | 
 |  | 
 | ### Debugging delayed bugs | 
 |  | 
 | The `-Z eagerly-emit-delayed-bugs` option makes it easy to debug delayed bugs. | 
 | It turns them into normal errors, i.e. makes them visible. This can be used in | 
 | combination with `-Z treat-err-as-bug` to stop at a particular delayed bug and | 
 | get a backtrace. | 
 |  | 
 | ### Getting the error creation location | 
 |  | 
 | `-Z track-diagnostics` can help figure out where errors are emitted. It uses `#[track_caller]` | 
 | for this and prints its location alongside the error: | 
 |  | 
 | ``` | 
 | $ RUST_BACKTRACE=1 rustc +stage1 error.rs -Z track-diagnostics | 
 | error[E0277]: cannot add `()` to `{integer}` | 
 |  --> src\error.rs:2:7 | 
 |   | | 
 | 2 |     1 + (); | 
 |   |       ^ no implementation for `{integer} + ()` | 
 | -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs:638:39 | 
 |   | | 
 |   = help: the trait `Add<()>` is not implemented for `{integer}` | 
 |   = help: the following other types implement trait `Add<Rhs>`: | 
 |             <&'a f32 as Add<f32>> | 
 |             <&'a f64 as Add<f64>> | 
 |             <&'a i128 as Add<i128>> | 
 |             <&'a i16 as Add<i16>> | 
 |             <&'a i32 as Add<i32>> | 
 |             <&'a i64 as Add<i64>> | 
 |             <&'a i8 as Add<i8>> | 
 |             <&'a isize as Add<isize>> | 
 |           and 48 others | 
 |  | 
 | For more information about this error, try `rustc --explain E0277`. | 
 | ``` | 
 |  | 
 | This is similar but different to `-Z treat-err-as-bug`: | 
 | - it will print the locations for all errors emitted | 
 | - it does not require a compiler built with debug symbols | 
 | - you don't have to read through a big stack trace. | 
 |  | 
 | ## Getting logging output | 
 |  | 
 | The compiler uses the [`tracing`] crate for logging. | 
 |  | 
 | [`tracing`]: https://docs.rs/tracing | 
 |  | 
 | For details see [the guide section on tracing](./tracing.md) | 
 |  | 
 | ## Narrowing (Bisecting) Regressions | 
 |  | 
 | The [cargo-bisect-rustc][bisect] tool can be used as a quick and easy way to | 
 | find exactly which PR caused a change in `rustc` behavior. It automatically | 
 | downloads `rustc` PR artifacts and tests them against a project you provide | 
 | until it finds the regression. You can then look at the PR to get more context | 
 | on *why* it was changed.  See [this tutorial][bisect-tutorial] on how to use | 
 | it. | 
 |  | 
 | [bisect]: https://github.com/rust-lang/cargo-bisect-rustc | 
 | [bisect-tutorial]: https://rust-lang.github.io/cargo-bisect-rustc/tutorial.html | 
 |  | 
 | ## Downloading Artifacts from Rust's CI | 
 |  | 
 | The [rustup-toolchain-install-master][rtim] tool by kennytm can be used to | 
 | download the artifacts produced by Rust's CI for a specific SHA1 -- this | 
 | basically corresponds to the successful landing of some PR -- and then sets | 
 | them up for your local use. This also works for artifacts produced by `@bors | 
 | try`. This is helpful when you want to examine the resulting build of a PR | 
 | without doing the build yourself. | 
 |  | 
 | [rtim]: https://github.com/kennytm/rustup-toolchain-install-master | 
 |  | 
 | ## `#[rustc_*]` TEST attributes | 
 |  | 
 | The compiler defines a whole lot of internal (perma-unstable) attributes some of which are useful | 
 | for debugging by dumping extra compiler-internal information. These are prefixed with `rustc_` and | 
 | are gated behind the internal feature `rustc_attrs` (enabled via e.g. `#![feature(rustc_attrs)]`). | 
 |  | 
 | For a complete and up to date list, see [`builtin_attrs`]. More specifically, the ones marked `TEST`. | 
 | Here are some notable ones: | 
 |  | 
 | | Attribute | Description | | 
 | |----------------|-------------| | 
 | | `rustc_def_path` | Dumps the [`def_path_str`] of an item. | | 
 | | `rustc_dump_def_parents` | Dumps the chain of `DefId` parents of certain definitions. | | 
 | | `rustc_dump_item_bounds` | Dumps the [`item_bounds`] of an item. | | 
 | | `rustc_dump_predicates` | Dumps the [`predicates_of`] an item. | | 
 | | `rustc_dump_vtable` | Dumps the vtable layout of an impl, or a type alias of a dyn type. | | 
 | | `rustc_hidden_type_of_opaques` | Dumps the [hidden type of each opaque types][opaq] in the crate. | | 
 | | `rustc_layout` | [See this section](#debugging-type-layouts). | | 
 | | `rustc_object_lifetime_default` | Dumps the [object lifetime defaults] of an item. | | 
 | | `rustc_outlives` | Dumps implied bounds of an item. More precisely, the [`inferred_outlives_of`] an item. | | 
 | | `rustc_regions` | Dumps NLL closure region requirements. | | 
 | | `rustc_symbol_name` | Dumps the mangled & demangled [`symbol_name`] of an item. | | 
 | | `rustc_variances` | Dumps the [variances] of an item. | | 
 |  | 
 | Right below you can find elaborate explainers on a selected few. | 
 |  | 
 | [`builtin_attrs`]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_feature/src/builtin_attrs.rs | 
 | [`def_path_str`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.def_path_str | 
 | [`inferred_outlives_of`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.inferred_outlives_of | 
 | [`item_bounds`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.item_bounds | 
 | [`predicates_of`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.predicates_of | 
 | [`symbol_name`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.symbol_name | 
 | [object lifetime defaults]: https://doc.rust-lang.org/reference/lifetime-elision.html#default-trait-object-lifetimes | 
 | [opaq]: ./opaque-types-impl-trait-inference.md | 
 | [variances]: ./variance.md | 
 |  | 
 | ### Formatting Graphviz output (.dot files) | 
 | [formatting-graphviz-output]: #formatting-graphviz-output | 
 |  | 
 | Some compiler options for debugging specific features yield graphviz graphs - | 
 | e.g. the `#[rustc_mir(borrowck_graphviz_postflow="suffix.dot")]` attribute | 
 | on a function dumps various borrow-checker dataflow graphs in conjunction with | 
 | `-Zdump-mir-dataflow`. | 
 |  | 
 | These all produce `.dot` files. To view these files, install graphviz (e.g. | 
 | `apt-get install graphviz`) and then run the following commands: | 
 |  | 
 | ```bash | 
 | $ dot -T pdf maybe_init_suffix.dot > maybe_init_suffix.pdf | 
 | $ firefox maybe_init_suffix.pdf # Or your favorite pdf viewer | 
 | ``` | 
 |  | 
 | ### Debugging type layouts | 
 |  | 
 | The internal attribute `#[rustc_layout]` can be used to dump the [`Layout`] of | 
 | the type it is attached to. For example: | 
 |  | 
 | ```rust | 
 | #![feature(rustc_attrs)] | 
 |  | 
 | #[rustc_layout(debug)] | 
 | type T<'a> = &'a u32; | 
 | ``` | 
 |  | 
 | Will emit the following: | 
 |  | 
 | ```text | 
 | error: layout_of(&'a u32) = Layout { | 
 |     fields: Primitive, | 
 |     variants: Single { | 
 |         index: 0, | 
 |     }, | 
 |     abi: Scalar( | 
 |         Scalar { | 
 |             value: Pointer, | 
 |             valid_range: 1..=18446744073709551615, | 
 |         }, | 
 |     ), | 
 |     largest_niche: Some( | 
 |         Niche { | 
 |             offset: Size { | 
 |                 raw: 0, | 
 |             }, | 
 |             scalar: Scalar { | 
 |                 value: Pointer, | 
 |                 valid_range: 1..=18446744073709551615, | 
 |             }, | 
 |         }, | 
 |     ), | 
 |     align: AbiAndPrefAlign { | 
 |         abi: Align { | 
 |             pow2: 3, | 
 |         }, | 
 |         pref: Align { | 
 |             pow2: 3, | 
 |         }, | 
 |     }, | 
 |     size: Size { | 
 |         raw: 8, | 
 |     }, | 
 | } | 
 |  --> src/lib.rs:4:1 | 
 |   | | 
 | 4 | type T<'a> = &'a u32; | 
 |   | ^^^^^^^^^^^^^^^^^^^^^ | 
 |  | 
 | error: aborting due to previous error | 
 | ``` | 
 |  | 
 | [`Layout`]: https://doc.rust-lang.org/nightly/nightly-rustc/stable_mir/abi/struct.Layout.html | 
 |  | 
 |  | 
 | ## Configuring CodeLLDB for debugging `rustc` | 
 |  | 
 | If you are using VSCode, and have edited your `bootstrap.toml` to request debugging | 
 | level 1 or 2 for the parts of the code you're interested in, then you should be | 
 | able to use the [CodeLLDB] extension in VSCode to debug it. | 
 |  | 
 | Here is a sample `launch.json` file, being used to run a stage 1 compiler direct | 
 | from the directory where it is built (does not have to be "installed"): | 
 |  | 
 | ```javascript | 
 | // .vscode/launch.json | 
 | { | 
 |     "version": "0.2.0", | 
 |     "configurations": [ | 
 |       { | 
 |         "type": "lldb", | 
 |         "request": "launch", | 
 |         "name": "Launch", | 
 |         "args": [],  // array of string command-line arguments to pass to compiler | 
 |         "program": "${workspaceFolder}/build/host/stage1/bin/rustc", | 
 |         "windows": {  // applicable if using windows | 
 |             "program": "${workspaceFolder}/build/host/stage1/bin/rustc.exe" | 
 |         }, | 
 |         "cwd": "${workspaceFolder}",  // current working directory at program start | 
 |         "stopOnEntry": false, | 
 |         "sourceLanguages": ["rust"] | 
 |       } | 
 |     ] | 
 |   } | 
 | ``` | 
 |  | 
 | [CodeLLDB]: https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb |