Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 7bae49a

Browse files
committed
Fix Issue 21030 - Reduce template function instantiations related to array equality
1 parent 93f0563 commit 7bae49a

1 file changed

Lines changed: 34 additions & 27 deletions

File tree

src/core/internal/array/equality.d

Lines changed: 34 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,50 @@ bool __ArrayEq(T1, T2)(T1[] a, T2[] b)
2323
return true;
2424
}
2525

26+
// `lhs == rhs` lowers to `__equals(lhs, rhs)` for dynamic arrays
27+
// The scalar-only overload takes advantage of known properties of scalars to
28+
// consolidate IFTI instances and remove the need for helper functions.
29+
bool __equals(T1, T2)(scope const T1[] lhs, scope const T2[] rhs)
30+
@nogc nothrow pure @trusted
31+
if (__traits(isScalar, T1) && __traits(isScalar, T2))
32+
{
33+
if (lhs.length != rhs.length)
34+
return false;
35+
static if (T1.sizeof == T2.sizeof
36+
&& __traits(isUnsigned, T1) == __traits(isUnsigned, T2)
37+
&& !__traits(isFloating, T1) && !__traits(isFloating, T2))
38+
{
39+
if (!__ctfe)
40+
{
41+
// This would improperly allow equality of integers and pointers
42+
// but the CTFE branch will stop this function from compiling then.
43+
import core.stdc.string : memcmp;
44+
return lhs.length == 0 || 0 == memcmp(lhs.ptr, rhs.ptr, lhs.length * T1.sizeof);
45+
}
46+
}
47+
foreach (const i; 0 .. lhs.length)
48+
if (lhs.ptr[i] != rhs.ptr[i])
49+
return false;
50+
return true;
51+
}
52+
53+
pragma(inline, true)
54+
private @trusted ref at(R)(return scope inout(R)[] r, size_t i) { return r.ptr[i]; }
55+
pragma(inline, true)
56+
private @trusted R trustedCast(R, S)(return scope S[] r) { return cast(R) r; }
57+
2658
// `lhs == rhs` lowers to `__equals(lhs, rhs)` for dynamic arrays
2759
bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
60+
if (!__traits(isScalar, T1) || !__traits(isScalar, T2))
2861
{
2962
import core.internal.traits : Unqual;
3063
alias U1 = Unqual!T1;
3164
alias U2 = Unqual!T2;
3265

33-
static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; }
34-
static @trusted R trustedCast(R, S)(S[] r) { return cast(R) r; }
35-
3666
if (lhs.length != rhs.length)
3767
return false;
3868

39-
if (lhs.length == 0 && rhs.length == 0)
69+
if (lhs.length == 0)
4070
return true;
4171

4272
static if (is(U1 == void) && is(U2 == void))
@@ -64,24 +94,6 @@ bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
6494
}
6595
return true;
6696
}
67-
else static if (__traits(isIntegral, U1))
68-
{
69-
70-
if (!__ctfe)
71-
{
72-
import core.stdc.string : memcmp;
73-
return () @trusted { return memcmp(cast(void*)lhs.ptr, cast(void*)rhs.ptr, lhs.length * U1.sizeof) == 0; }();
74-
}
75-
else
76-
{
77-
foreach (const u; 0 .. lhs.length)
78-
{
79-
if (at(lhs, u) != at(rhs, u))
80-
return false;
81-
}
82-
return true;
83-
}
84-
}
8597
else
8698
{
8799
foreach (const u; 0 .. lhs.length)
@@ -91,11 +103,6 @@ bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
91103
if (!__equals(at(lhs, u), at(rhs, u)))
92104
return false;
93105
}
94-
else static if (__traits(isFloating, U1))
95-
{
96-
if (at(lhs, u) != at(rhs, u))
97-
return false;
98-
}
99106
else static if (is(U1 : Object) && is(U2 : Object))
100107
{
101108
if (!(cast(Object)at(lhs, u) is cast(Object)at(rhs, u)

0 commit comments

Comments
 (0)