You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 { location: Location { file: "refcell_test.rs", line: 6, col: 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 { location: Location { file: "refcell_test.rs", line: 16, col: 27 } }', refcell_test.rs:18:25
```
0 commit comments