mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-02 15:32:06 +00:00
9b6339e4b9
Add `debug-refcell` feature to libcore See https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/Attaching.20backtraces.20to.20RefCell/near/226273614 for some background discussion This PR adds a new off-by-default feature `debug-refcell` to libcore. When enabled, this feature stores additional debugging information in `RefCell`. This information is included in the panic message when `borrow()` or `borrow_mut()` panics, to make it easier to track down the source of the issue. Currently, we store the caller location for the earliest active borrow. This has a number of advantages: * There is only a constant amount of overhead per `RefCell` * We don't need any heap memory, so it can easily be implemented in core * Since we are storing the *earliest* active borrow, we don't need any extra logic in the `Drop` implementation for `Ref` and `RefMut` Limitations: * We only store the caller location, not a full `Backtrace`. Until we get support for `Backtrace` in libcore, this is the best tha we can do. * The captured location is only displayed when `borrow()` or `borrow_mut()` panics. If a crate calls `try_borrow().unwrap()` or `try_borrow_mut().unwrap()`, this extra information will be lost. To make testing easier, I've enabled the `debug-refcell` feature by default. I'm not sure how to write a test for this feature - we would need to rebuild core from the test framework, and create a separate sysroot. Since this feature will be off-by-default, users will need to use `xargo` or `cargo -Z build-std` to enable this feature. For users using a prebuilt standard library, this feature will be disabled with zero overhead. I've created a simple test program: ```rust use std::cell::RefCell; fn main() { let _ = std::panic::catch_unwind(|| { let val = RefCell::new(true); let _first = val.borrow(); let _second = val.borrow(); let _third = val.borrow_mut(); }); let _ = std::panic::catch_unwind(|| { let val = RefCell::new(true); let first = val.borrow_mut(); drop(first); let _second = val.borrow_mut(); let _thid = val.borrow(); }); } ``` which produces the following output: ``` thread 'main' panicked at 'already borrowed: BorrowMutError at refcell_test.rs:6:26', refcell_test.rs:8:26 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace thread 'main' panicked at 'already mutably borrowed: BorrowError at refcell_test.rs:16:27', refcell_test.rs:18:25 ``` |
||
---|---|---|
.. | ||
alloc | ||
backtrace@af078ecc0b | ||
core | ||
panic_abort | ||
panic_unwind | ||
proc_macro | ||
profiler_builtins | ||
rtstartup | ||
rustc-std-workspace-alloc | ||
rustc-std-workspace-core | ||
rustc-std-workspace-std | ||
std | ||
stdarch@9c732a56f6 | ||
term | ||
test | ||
unwind |