|
1 | 1 | use std::any::Any;
|
2 |
| -use std::cell::RefCell; |
| 2 | +use std::cell::{Cell, RefCell}; |
3 | 3 | use std::iter::TrustedLen;
|
4 | 4 | use std::mem;
|
5 | 5 | use std::sync::{Arc, Weak};
|
@@ -89,7 +89,7 @@ fn eq() {
|
89 | 89 |
|
90 | 90 | // The test code below is identical to that in `rc.rs`.
|
91 | 91 | // For better maintainability we therefore define this type alias.
|
92 |
| -type Rc<T> = Arc<T>; |
| 92 | +type Rc<T, A = std::alloc::Global> = Arc<T, A>; |
93 | 93 |
|
94 | 94 | const SHARED_ITER_MAX: u16 = 100;
|
95 | 95 |
|
@@ -210,6 +210,42 @@ fn weak_may_dangle() {
|
210 | 210 | // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::sync::Weak`
|
211 | 211 | }
|
212 | 212 |
|
| 213 | +/// Test that a panic from a destructor does not leak the allocation. |
| 214 | +#[test] |
| 215 | +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] |
| 216 | +fn panic_no_leak() { |
| 217 | + use std::alloc::{AllocError, Allocator, Global, Layout}; |
| 218 | + use std::panic::{AssertUnwindSafe, catch_unwind}; |
| 219 | + use std::ptr::NonNull; |
| 220 | + |
| 221 | + struct AllocCount(Cell<i32>); |
| 222 | + unsafe impl Allocator for AllocCount { |
| 223 | + fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> { |
| 224 | + self.0.set(self.0.get() + 1); |
| 225 | + Global.allocate(layout) |
| 226 | + } |
| 227 | + unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { |
| 228 | + self.0.set(self.0.get() - 1); |
| 229 | + unsafe { Global.deallocate(ptr, layout) } |
| 230 | + } |
| 231 | + } |
| 232 | + |
| 233 | + struct PanicOnDrop; |
| 234 | + impl Drop for PanicOnDrop { |
| 235 | + fn drop(&mut self) { |
| 236 | + panic!("PanicOnDrop"); |
| 237 | + } |
| 238 | + } |
| 239 | + |
| 240 | + let alloc = AllocCount(Cell::new(0)); |
| 241 | + let rc = Rc::new_in(PanicOnDrop, &alloc); |
| 242 | + assert_eq!(alloc.0.get(), 1); |
| 243 | + |
| 244 | + let panic_message = catch_unwind(AssertUnwindSafe(|| drop(rc))).unwrap_err(); |
| 245 | + assert_eq!(*panic_message.downcast_ref::<&'static str>().unwrap(), "PanicOnDrop"); |
| 246 | + assert_eq!(alloc.0.get(), 0); |
| 247 | +} |
| 248 | + |
213 | 249 | /// This is similar to the doc-test for `Arc::make_mut()`, but on an unsized type (slice).
|
214 | 250 | #[test]
|
215 | 251 | fn make_mut_unsized() {
|
|
0 commit comments