@@ -7,6 +7,7 @@ use std::mem::{size_of, swap};
77use std:: ops:: Bound :: * ;
88use std:: panic:: { catch_unwind, AssertUnwindSafe } ;
99use std:: rc:: Rc ;
10+ use std:: sync:: atomic:: { AtomicU32 , Ordering } ;
1011use std:: vec:: { Drain , IntoIter } ;
1112
1213struct DropCounter < ' a > {
@@ -2100,3 +2101,44 @@ fn test_extend_from_within() {
21002101
21012102 assert_eq ! ( v, [ "a" , "b" , "c" , "b" , "c" , "a" , "b" ] ) ;
21022103}
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