1010
1111module core.internal.array.equality ;
1212
13+ // `lhs == rhs` lowers to `__equals(lhs, rhs)` for dynamic arrays
14+ // The scalar-only overload takes advantage of known properties of scalars to
15+ // consolidate IFTI instances and remove the need for helper functions.
16+ bool __equals (T1 , T2 )(scope const T1 [] lhs, scope const T2 [] rhs)
17+ @nogc nothrow pure @trusted
18+ if (__traits(isScalar, T1 ) && __traits(isScalar, T2 ))
19+ {
20+ if (lhs.length != rhs.length)
21+ return false ;
22+ static if (T1 .sizeof == T2 .sizeof
23+ // Signedness needs to match for types that promote to int.
24+ && (T1 .sizeof >= 4 || __traits(isUnsigned, T1 ) == __traits(isUnsigned, T2 ))
25+ && ! __traits(isFloating, T1 ) && ! __traits(isFloating, T2 ))
26+ {
27+ if (! __ctfe)
28+ {
29+ // This would improperly allow equality of integers and pointers
30+ // but the CTFE branch will stop this function from compiling then.
31+ import core.stdc.string : memcmp;
32+ return lhs.length == 0 || 0 == memcmp(lhs.ptr, rhs.ptr, lhs.length * T1 .sizeof);
33+ }
34+ }
35+ foreach (const i; 0 .. lhs.length)
36+ if (lhs.ptr[i] != rhs.ptr[i])
37+ return false ;
38+ return true ;
39+ }
40+
41+ pragma (inline, true )
42+ private @trusted R trustedCast(R, S)(return scope S[] r) { return cast (R) r; }
43+ pragma (inline, true )
44+ private @trusted ref at(T)(return scope T[] r, size_t i)
45+ // exclude opaque structs due to https://issues.dlang.org/show_bug.cgi?id=20959
46+ if (! (is (T == struct ) && ! is (typeof (T.sizeof))))
47+ {
48+ return r.ptr[i];
49+ }
50+
1351 // `lhs == rhs` lowers to `__equals(lhs, rhs)` for dynamic arrays
1452bool __equals (T1 , T2 )(T1 [] lhs, T2 [] rhs)
53+ if (! __traits(isScalar, T1 ) || ! __traits(isScalar, T2 ))
1554{
1655 import core.internal.traits : Unqual;
1756 alias U1 = Unqual! T1 ;
1857 alias U2 = Unqual! T2 ;
1958
20- static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; }
21- static @trusted R trustedCast(R, S)(S[] r) { return cast (R) r; }
22-
2359 if (lhs.length != rhs.length)
2460 return false ;
2561
26- if (lhs.length == 0 && rhs.length == 0 )
62+ if (lhs.length == 0 )
2763 return true ;
2864
2965 static if (is (U1 == void ) && is (U2 == void ))
@@ -47,24 +83,6 @@ bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
4783 }
4884 return true ;
4985 }
50- else static if (__traits(isIntegral, U1 ))
51- {
52-
53- if (! __ctfe)
54- {
55- import core.stdc.string : memcmp;
56- return () @trusted { return memcmp(cast (void * )lhs.ptr, cast (void * )rhs.ptr, lhs.length * U1 .sizeof) == 0 ; }();
57- }
58- else
59- {
60- foreach (const u; 0 .. lhs.length)
61- {
62- if (at(lhs, u) != at(rhs, u))
63- return false ;
64- }
65- return true ;
66- }
67- }
6886 else
6987 {
7088 foreach (const u; 0 .. lhs.length)
@@ -74,11 +92,6 @@ bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
7492 if (! __equals(at(lhs, u), at(rhs, u)))
7593 return false ;
7694 }
77- else static if (__traits(isFloating, U1 ))
78- {
79- if (at(lhs, u) != at(rhs, u))
80- return false ;
81- }
8295 else static if (is (U1 : Object ) && is (U2 : Object ))
8396 {
8497 if (! (cast (Object )at(lhs, u) is cast (Object )at(rhs, u)
0 commit comments