@@ -2,12 +2,16 @@ use rustc_index::vec::{Idx, IndexVec};
2
2
use std:: mem;
3
3
use std:: ptr;
4
4
5
- pub trait IdFunctor {
5
+ pub trait IdFunctor : Sized {
6
6
type Inner ;
7
7
8
8
fn map_id < F > ( self , f : F ) -> Self
9
9
where
10
10
F : FnMut ( Self :: Inner ) -> Self :: Inner ;
11
+
12
+ fn try_map_id < F , E > ( self , f : F ) -> Result < Self , E >
13
+ where
14
+ F : FnMut ( Self :: Inner ) -> Result < Self :: Inner , E > ;
11
15
}
12
16
13
17
impl < T > IdFunctor for Box < T > {
@@ -31,6 +35,25 @@ impl<T> IdFunctor for Box<T> {
31
35
raw. assume_init ( )
32
36
}
33
37
}
38
+
39
+ #[ inline]
40
+ fn try_map_id < F , E > ( self , mut f : F ) -> Result < Self , E >
41
+ where
42
+ F : FnMut ( Self :: Inner ) -> Result < Self :: Inner , E > ,
43
+ {
44
+ let raw = Box :: into_raw ( self ) ;
45
+ Ok ( unsafe {
46
+ // SAFETY: The raw pointer points to a valid value of type `T`.
47
+ let value = ptr:: read ( raw) ;
48
+ // SAFETY: Converts `Box<T>` to `Box<MaybeUninit<T>>` which is the
49
+ // inverse of `Box::assume_init()` and should be safe.
50
+ let mut raw: Box < mem:: MaybeUninit < T > > = Box :: from_raw ( raw. cast ( ) ) ;
51
+ // SAFETY: Write the mapped value back into the `Box`.
52
+ ptr:: write ( raw. as_mut_ptr ( ) , f ( value) ?) ;
53
+ // SAFETY: We just initialized `raw`.
54
+ raw. assume_init ( )
55
+ } )
56
+ }
34
57
}
35
58
36
59
impl < T > IdFunctor for Vec < T > {
@@ -55,6 +78,35 @@ impl<T> IdFunctor for Vec<T> {
55
78
}
56
79
self
57
80
}
81
+
82
+ #[ inline]
83
+ fn try_map_id < F , E > ( mut self , mut f : F ) -> Result < Self , E >
84
+ where
85
+ F : FnMut ( Self :: Inner ) -> Result < Self :: Inner , E > ,
86
+ {
87
+ // FIXME: We don't really care about panics here and leak
88
+ // far more than we should, but that should be fine for now.
89
+ let len = self . len ( ) ;
90
+ let mut error = Ok ( ( ) ) ;
91
+ unsafe {
92
+ self . set_len ( 0 ) ;
93
+ let start = self . as_mut_ptr ( ) ;
94
+ for i in 0 ..len {
95
+ let p = start. add ( i) ;
96
+ match f ( ptr:: read ( p) ) {
97
+ Ok ( value) => ptr:: write ( p, value) ,
98
+ Err ( err) => {
99
+ error = Err ( err) ;
100
+ break ;
101
+ }
102
+ }
103
+ }
104
+ // Even if we encountered an error, set the len back
105
+ // so we don't leak memory.
106
+ self . set_len ( len) ;
107
+ }
108
+ error. map ( |( ) | self )
109
+ }
58
110
}
59
111
60
112
impl < T > IdFunctor for Box < [ T ] > {
@@ -67,6 +119,14 @@ impl<T> IdFunctor for Box<[T]> {
67
119
{
68
120
Vec :: from ( self ) . map_id ( f) . into ( )
69
121
}
122
+
123
+ #[ inline]
124
+ fn try_map_id < F , E > ( self , f : F ) -> Result < Self , E >
125
+ where
126
+ F : FnMut ( Self :: Inner ) -> Result < Self :: Inner , E > ,
127
+ {
128
+ Vec :: from ( self ) . try_map_id ( f) . map ( Into :: into)
129
+ }
70
130
}
71
131
72
132
impl < I : Idx , T > IdFunctor for IndexVec < I , T > {
@@ -79,4 +139,12 @@ impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
79
139
{
80
140
IndexVec :: from_raw ( self . raw . map_id ( f) )
81
141
}
142
+
143
+ #[ inline]
144
+ fn try_map_id < F , E > ( self , f : F ) -> Result < Self , E >
145
+ where
146
+ F : FnMut ( Self :: Inner ) -> Result < Self :: Inner , E > ,
147
+ {
148
+ self . raw . try_map_id ( f) . map ( IndexVec :: from_raw)
149
+ }
82
150
}
0 commit comments