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

Commit bdb3810

Browse files
committed
Fix Issue 21030 - Reduce template function instantiations related to array equality
1 parent 54197db commit bdb3810

1 file changed

Lines changed: 40 additions & 27 deletions

File tree

src/core/internal/array/equality.d

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,56 @@
1010

1111
module 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
1452
bool __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

Comments
 (0)