Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions src/core/internal/array/equality.d
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,41 @@ module core.internal.array.equality;
// * dynamic arrays,
// * (most) arrays of different (unqualified) element types, and
// * arrays of structs with custom opEquals.

// The scalar-only overload takes advantage of known properties of scalars to
// reduce template instantiation. This is expected to be the most common case.
bool __equals(T1, T2)(scope const T1[] lhs, scope const T2[] rhs)
@nogc nothrow pure @trusted
if (__traits(isScalar, T1) && __traits(isScalar, T2))
{
if (lhs.length != rhs.length)
return false;

static if (T1.sizeof == T2.sizeof
// Signedness needs to match for types that promote to int.
// (Actually it would be okay to memcmp bool[] and byte[] but that is
// probably too uncommon to be worth checking for.)
&& (T1.sizeof >= 4 || __traits(isUnsigned, T1) == __traits(isUnsigned, T2))
&& !__traits(isFloating, T1) && !__traits(isFloating, T2))
{
if (!__ctfe)
{
// This would improperly allow equality of integers and pointers
// but the CTFE branch will stop this function from compiling then.
import core.stdc.string : memcmp;
return lhs.length == 0 ||
0 == memcmp(cast(const void*) lhs.ptr, cast(const void*) rhs.ptr, lhs.length * T1.sizeof);
}
}

foreach (const i; 0 .. lhs.length)
if (lhs.ptr[i] != rhs.ptr[i])
return false;
return true;
}

bool __equals(T1, T2)(scope T1[] lhs, scope T2[] rhs)
if (!__traits(isScalar, T1) || !__traits(isScalar, T2))
{
if (lhs.length != rhs.length)
return false;
Expand Down