@@ -148,3 +148,76 @@ impl_disjoint_bitor! {
148148 u8 , u16 , u32 , u64 , u128 , usize ,
149149 i8 , i16 , i32 , i64 , i128 , isize ,
150150}
151+
152+ #[ const_trait]
153+ #[ rustc_const_unstable( feature = "core_intrinsics_fallbacks" , issue = "none" ) ]
154+ pub trait FunnelShift : Copy + ' static {
155+ /// See [`super::unchecked_funnel_shl`]; we just need the trait indirection to handle
156+ /// different types since calling intrinsics with generics doesn't work.
157+ unsafe fn unchecked_funnel_shl ( self , rhs : Self , shift : u32 ) -> Self ;
158+
159+ /// See [`super::unchecked_funnel_shr`]; we just need the trait indirection to handle
160+ /// different types since calling intrinsics with generics doesn't work.
161+ unsafe fn unchecked_funnel_shr ( self , rhs : Self , shift : u32 ) -> Self ;
162+ }
163+
164+ macro_rules! impl_funnel_shifts {
165+ ( $( $type: ident) ,* ) => { $(
166+ #[ rustc_const_unstable( feature = "core_intrinsics_fallbacks" , issue = "none" ) ]
167+ impl const FunnelShift for $type {
168+ #[ cfg_attr( miri, track_caller) ]
169+ #[ inline]
170+ unsafe fn unchecked_funnel_shl( self , rhs: Self , shift: u32 ) -> Self {
171+ // This implementation is also used by Miri so we have to check the precondition.
172+ // SAFETY: this is guaranteed by the caller
173+ unsafe { super :: assume( shift < $type:: BITS ) } ;
174+ if shift == 0 {
175+ self
176+ } else {
177+ // SAFETY:
178+ // - `shift < T::BITS`, which satisfies `unchecked_shl`
179+ // - this also ensures that `T::BITS - shift < T::BITS` (shift = 0 is checked
180+ // above), which satisfies `unchecked_shr`
181+ // - because the types are unsigned, the combination are disjoint bits (this is
182+ // not true if they're signed, since SHR will fill in the empty space with a
183+ // sign bit, not zero)
184+ unsafe {
185+ super :: disjoint_bitor(
186+ super :: unchecked_shl( self , shift) ,
187+ super :: unchecked_shr( rhs, $type:: BITS - shift) ,
188+ )
189+ }
190+ }
191+ }
192+
193+ #[ cfg_attr( miri, track_caller) ]
194+ #[ inline]
195+ unsafe fn unchecked_funnel_shr( self , rhs: Self , shift: u32 ) -> Self {
196+ // This implementation is also used by Miri so we have to check the precondition.
197+ // SAFETY: this is guaranteed by the caller
198+ unsafe { super :: assume( shift < $type:: BITS ) } ;
199+ if shift == 0 {
200+ rhs
201+ } else {
202+ // SAFETY:
203+ // - `shift < T::BITS`, which satisfies `unchecked_shr`
204+ // - this also ensures that `T::BITS - shift < T::BITS` (shift = 0 is checked
205+ // above), which satisfies `unchecked_shl`
206+ // - because the types are unsigned, the combination are disjoint bits (this is
207+ // not true if they're signed, since SHR will fill in the empty space with a
208+ // sign bit, not zero)
209+ unsafe {
210+ super :: disjoint_bitor(
211+ super :: unchecked_shl( self , $type:: BITS - shift) ,
212+ super :: unchecked_shr( rhs, shift) ,
213+ )
214+ }
215+ }
216+ }
217+ }
218+ ) * } ;
219+ }
220+
221+ impl_funnel_shifts ! {
222+ u8 , u16 , u32 , u64 , u128 , usize
223+ }
0 commit comments