@@ -2,12 +2,16 @@ use rustc_index::vec::{Idx, IndexVec};
22use std:: mem;
33use std:: ptr;
44
5- pub trait IdFunctor {
5+ pub trait IdFunctor : Sized {
66 type Inner ;
77
88 fn map_id < F > ( self , f : F ) -> Self
99 where
1010 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 > ;
1115}
1216
1317impl < T > IdFunctor for Box < T > {
@@ -31,6 +35,25 @@ impl<T> IdFunctor for Box<T> {
3135 raw. assume_init ( )
3236 }
3337 }
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+ }
3457}
3558
3659impl < T > IdFunctor for Vec < T > {
@@ -55,6 +78,35 @@ impl<T> IdFunctor for Vec<T> {
5578 }
5679 self
5780 }
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+ }
58110}
59111
60112impl < T > IdFunctor for Box < [ T ] > {
@@ -67,6 +119,14 @@ impl<T> IdFunctor for Box<[T]> {
67119 {
68120 Vec :: from ( self ) . map_id ( f) . into ( )
69121 }
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+ }
70130}
71131
72132impl < I : Idx , T > IdFunctor for IndexVec < I , T > {
@@ -79,4 +139,12 @@ impl<I: Idx, T> IdFunctor for IndexVec<I, T> {
79139 {
80140 IndexVec :: from_raw ( self . raw . map_id ( f) )
81141 }
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+ }
82150}
0 commit comments