@@ -34,38 +34,43 @@ impl<T> IdFunctor for Vec<T> {
34
34
type Inner = T ;
35
35
36
36
#[ 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 >
38
38
where
39
39
F : FnMut ( Self :: Inner ) -> Result < Self :: Inner , E > ,
40
40
{
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
+ }
57
45
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
+ }
61
53
}
62
54
}
63
55
}
64
- // Even if we encountered an error, set the len back
65
- // so we don't leak memory.
66
- self . set_len ( len) ;
67
56
}
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
+ }
69
74
}
70
75
}
71
76
0 commit comments