@@ -7,6 +7,7 @@ use std::mem::{size_of, swap};
7
7
use std:: ops:: Bound :: * ;
8
8
use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
9
9
use std:: rc:: Rc ;
10
+ use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
10
11
use std:: vec:: { Drain , IntoIter } ;
11
12
12
13
struct DropCounter < ' a > {
@@ -2100,3 +2101,44 @@ fn test_extend_from_within() {
2100
2101
2101
2102
assert_eq ! ( v, [ "a" , "b" , "c" , "b" , "c" , "a" , "b" ] ) ;
2102
2103
}
2104
+
2105
+ // Regression test for issue #82533
2106
+ #[ test]
2107
+ fn test_extend_from_within_panicing_clone ( ) {
2108
+ struct Panic < ' dc > {
2109
+ drop_count : & ' dc AtomicU32 ,
2110
+ aaaaa : bool ,
2111
+ }
2112
+
2113
+ impl Clone for Panic < ' _ > {
2114
+ fn clone ( & self ) -> Self {
2115
+ if self . aaaaa {
2116
+ panic ! ( "panic! at the clone" ) ;
2117
+ }
2118
+
2119
+ Self { ..* self }
2120
+ }
2121
+ }
2122
+
2123
+ impl Drop for Panic < ' _ > {
2124
+ fn drop ( & mut self ) {
2125
+ self . drop_count . fetch_add ( 1 , Ordering :: SeqCst ) ;
2126
+ }
2127
+ }
2128
+
2129
+ let count = core:: sync:: atomic:: AtomicU32 :: new ( 0 ) ;
2130
+ let mut vec = vec ! [
2131
+ Panic { drop_count: & count, aaaaa: false } ,
2132
+ Panic { drop_count: & count, aaaaa: true } ,
2133
+ Panic { drop_count: & count, aaaaa: false } ,
2134
+ ] ;
2135
+
2136
+ // This should clone&append one Panic{..} at the end, and then panic while
2137
+ // cloning second Panic{..}. This means that `Panic::drop` should be called
2138
+ // 4 times (3 for items already in vector, 1 for just appended).
2139
+ //
2140
+ // Previously just appended item was leaked, making drop_count = 3, instead of 4.
2141
+ std:: panic:: catch_unwind ( move || vec. extend_from_within ( ..) ) . unwrap_err ( ) ;
2142
+
2143
+ assert_eq ! ( count. load( Ordering :: SeqCst ) , 4 ) ;
2144
+ }
0 commit comments