File tree 2 files changed +48
-1
lines changed
2 files changed +48
-1
lines changed Original file line number Diff line number Diff line change @@ -171,3 +171,17 @@ fn fold_to_last(b: &mut Bencher) {
171
171
let slice: & [ i32 ] = & [ 0 ; 1024 ] ;
172
172
b. iter ( || black_box ( slice) . iter ( ) . fold ( None , |_, r| Some ( NonNull :: from ( r) ) ) ) ;
173
173
}
174
+
175
+ #[ bench]
176
+ fn slice_cmp_generic ( b : & mut Bencher ) {
177
+ #[ derive( PartialEq , Clone , Copy ) ]
178
+ struct Foo ( u32 , u32 ) ;
179
+
180
+ let left = [ Foo ( 128 , 128 ) ; 128 ] ;
181
+ let right = [ Foo ( 128 , 128 ) ; 128 ] ;
182
+
183
+ b. iter ( || {
184
+ let ( left, right) = ( black_box ( & left) , black_box ( & right) ) ;
185
+ left. as_slice ( ) == right. as_slice ( )
186
+ } ) ;
187
+ }
Original file line number Diff line number Diff line change @@ -55,12 +55,45 @@ impl<A, B> SlicePartialEq<B> for [A]
55
55
where
56
56
A : PartialEq < B > ,
57
57
{
58
+ #[ inline]
58
59
default fn equal ( & self , other : & [ B ] ) -> bool {
59
60
if self . len ( ) != other. len ( ) {
60
61
return false ;
61
62
}
62
63
63
- self . iter ( ) . zip ( other. iter ( ) ) . all ( |( x, y) | x == y)
64
+ // ZSTs have no identity and slices don't guarantee which addresses-to-ZSTs they produce
65
+ // so we only need to compare them once to determine the behavior of the PartialEq impl
66
+ if const { mem:: size_of :: < A > ( ) == 0 && mem:: size_of :: < B > ( ) == 0 } {
67
+ // zero-length slices are always equal
68
+ if self . len ( ) == 0 {
69
+ return true ;
70
+ }
71
+ // SAFETY: A and B are ZSTs so it's ok to conjure them out of thin air
72
+ return unsafe { mem:: zeroed :: < A > ( ) == mem:: zeroed :: < B > ( ) } ;
73
+ }
74
+
75
+ const UNROLL : usize = 4 ;
76
+ let mut i = 0 ;
77
+ let mut is_eq = true ;
78
+ while i + UNROLL < self . len ( ) && is_eq {
79
+ // SAFETY: slices are of the same length and loop conditions ensure indexes are in bounds
80
+ unsafe {
81
+ is_eq = is_eq & ( self . get_unchecked ( i) == other. get_unchecked ( i) ) ;
82
+ is_eq = is_eq & ( self . get_unchecked ( i + 1 ) == other. get_unchecked ( i + 1 ) ) ;
83
+ is_eq = is_eq & ( self . get_unchecked ( i + 2 ) == other. get_unchecked ( i + 2 ) ) ;
84
+ is_eq = is_eq & ( self . get_unchecked ( i + 3 ) == other. get_unchecked ( i + 3 ) ) ;
85
+ i = i. unchecked_add ( UNROLL ) ;
86
+ }
87
+ }
88
+ while i < self . len ( ) && is_eq {
89
+ // SAFETY: slices are of the same length and loop conditions ensure indexes are in bounds
90
+ unsafe {
91
+ is_eq = is_eq & ( self . get_unchecked ( i) == other. get_unchecked ( i) ) ;
92
+ i = i. unchecked_add ( 1 ) ;
93
+ }
94
+ }
95
+
96
+ is_eq
64
97
}
65
98
}
66
99
You can’t perform that action at this time.
0 commit comments