@@ -21,8 +21,7 @@ bool __equals(T1, T2)(scope const T1[] lhs, scope const T2[] rhs)
2121@nogc nothrow pure @trusted
2222if (__traits(isScalar, T1 ) && __traits(isScalar, T2 ))
2323{
24- if (lhs.length != rhs.length)
25- return false ;
24+ const length = lhs.length;
2625
2726 static if (T1 .sizeof == T2 .sizeof
2827 // Signedness needs to match for types that promote to int.
@@ -31,20 +30,21 @@ if (__traits(isScalar, T1) && __traits(isScalar, T2))
3130 && (T1 .sizeof >= 4 || __traits(isUnsigned, T1 ) == __traits(isUnsigned, T2 ))
3231 && ! __traits(isFloating, T1 ) && ! __traits(isFloating, T2 ))
3332 {
34- if (! __ctfe)
33+ if (__ctfe)
34+ return length == rhs.length && isEqual(lhs.ptr, rhs.ptr, length);
35+ else
3536 {
3637 // This would improperly allow equality of integers and pointers
3738 // but the CTFE branch will stop this function from compiling then.
3839 import core.stdc.string : memcmp;
39- return lhs. length == 0 ||
40- 0 == memcmp(cast (const void * ) lhs.ptr, cast (const void * ) rhs.ptr, lhs. length * T1 .sizeof);
40+ return length == rhs.length &&
41+ ( ! length || 0 == memcmp(cast (const void * ) lhs.ptr, cast (const void * ) rhs.ptr, length * T1 .sizeof) );
4142 }
4243 }
43-
44- foreach (const i; 0 .. lhs.length)
45- if (lhs.ptr[i] != rhs.ptr[i])
46- return false ;
47- return true ;
44+ else
45+ {
46+ return length == rhs.length && isEqual(lhs.ptr, rhs.ptr, length);
47+ }
4848}
4949
5050bool __equals (T1 , T2 )(scope T1 [] lhs, scope T2 [] rhs)
@@ -89,6 +89,19 @@ if (!__traits(isScalar, T1) || !__traits(isScalar, T2))
8989 }
9090}
9191
92+ /* *****************************
93+ * Helper function for __equals().
94+ * Outlined to enable __equals() to be inlined, as dmd cannot inline loops.
95+ */
96+ private
97+ bool isEqual (T1 , T2 )(scope const T1 * t1, scope const T2 * t2, size_t length)
98+ {
99+ foreach (const i; 0 .. length)
100+ if (t1[i] != t2[i])
101+ return false ;
102+ return true ;
103+ }
104+
92105@safe unittest
93106{
94107 assert (__equals([], []));
0 commit comments