@@ -34,38 +34,43 @@ impl<T> IdFunctor for Vec<T> {
3434 type Inner = T ;
3535
3636 #[ inline]
37- fn try_map_id < F , E > ( mut self , mut f : F ) -> Result < Self , E >
37+ fn try_map_id < F , E > ( self , mut f : F ) -> Result < Self , E >
3838 where
3939 F : FnMut ( Self :: Inner ) -> Result < Self :: Inner , E > ,
4040 {
41- // FIXME: We don't really care about panics here and leak
42- // far more than we should, but that should be fine for now.
43- let len = self . len ( ) ;
44- unsafe {
45- self . set_len ( 0 ) ;
46- let start = self . as_mut_ptr ( ) ;
47- for i in 0 ..len {
48- let p = start. add ( i) ;
49- match f ( p. read ( ) ) {
50- Ok ( val) => p. write ( val) ,
51- Err ( err) => {
52- // drop all other elements in self
53- // (current element was "moved" into the call to f)
54- for j in ( 0 ..i) . chain ( i + 1 ..len) {
55- start. add ( j) . drop_in_place ( ) ;
56- }
41+ struct HoleVec < T > {
42+ vec : Vec < mem:: ManuallyDrop < T > > ,
43+ hole : Option < usize > ,
44+ }
5745
58- // returning will drop self, releasing the allocation
59- // (len is 0 so elements will not be re-dropped)
60- return Err ( err) ;
46+ impl < T > Drop for HoleVec < T > {
47+ fn drop ( & mut self ) {
48+ unsafe {
49+ for ( index, slot) in self . vec . iter_mut ( ) . enumerate ( ) {
50+ if self . hole != Some ( index) {
51+ mem:: ManuallyDrop :: drop ( slot) ;
52+ }
6153 }
6254 }
6355 }
64- // Even if we encountered an error, set the len back
65- // so we don't leak memory.
66- self . set_len ( len) ;
6756 }
68- Ok ( self )
57+
58+ unsafe {
59+ let ( ptr, length, capacity) = self . into_raw_parts ( ) ;
60+ let vec = Vec :: from_raw_parts ( ptr. cast ( ) , length, capacity) ;
61+ let mut hole_vec = HoleVec { vec, hole : None } ;
62+
63+ for ( index, slot) in hole_vec. vec . iter_mut ( ) . enumerate ( ) {
64+ hole_vec. hole = Some ( index) ;
65+ let original = mem:: ManuallyDrop :: take ( slot) ;
66+ let mapped = f ( original) ?;
67+ * slot = mem:: ManuallyDrop :: new ( mapped) ;
68+ hole_vec. hole = None ;
69+ }
70+
71+ mem:: forget ( hole_vec) ;
72+ Ok ( Vec :: from_raw_parts ( ptr, length, capacity) )
73+ }
6974 }
7075}
7176
0 commit comments