894 changes: 878 additions & 16 deletions src/object.d

Large diffs are not rendered by default.

201 changes: 189 additions & 12 deletions src/rt/util/typeinfo.d
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ module rt.util.typeinfo;
static import core.internal.hash;

template Floating(T)
if (is(T == float) || is(T == double) || is(T == real))
if (is(T == float) || is(T == double) || is(T == real)
|| is(T == ifloat) || is(T == idouble) || is(T == ireal))
{
pure nothrow @safe:
pure nothrow @safe @nogc:

bool equals(T f1, T f2)
{
Expand All @@ -20,25 +21,21 @@ if (is(T == float) || is(T == double) || is(T == real))

int compare(T d1, T d2)
{
if (d1 != d1 || d2 != d2) // if either are NaN
auto d = d1 - d2;
auto result = int(d > 0) - int(d < 0);
andralex marked this conversation as resolved.
Show resolved Hide resolved
if (!result && d != d) // if either are NaN
{
if (d1 != d1)
{
if (d2 != d2)
return 0;
return -1;
}
return 1;
return int(d1 == d1) - int(d2 == d2);
}
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
return result;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this refactoring objectively better? If it isn't, I find it significantly more difficult to understand.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's supposed to be faster

}

public alias hashOf = core.internal.hash.hashOf;
}
template Floating(T)
if (is(T == cfloat) || is(T == cdouble) || is(T == creal))
{
pure nothrow @safe:
pure nothrow @safe @nogc:

bool equals(T f1, T f2)
{
Expand Down Expand Up @@ -266,3 +263,183 @@ unittest
}
}();
}

// unittests for the new __typeid
unittest
{
// Bugzilla 13052

static struct SX(F) { F f; }

// real types
foreach (F; TypeTuple!(float, double, real))
(){ // workaround #2396
alias S = SX!F;
F f1 = +0.0,
f2 = -0.0;

assert(f1 == f2);
assert(f1 !is f2);

F[] a1 = [f1, f1, f1];
F[] a2 = [f2, f2, f2];

TypeInfo ti = __typeid!F;
assert(ti.getHash(&f1) == ti.getHash(&f2));

assert(a1 == a2);
assert(a1 !is a2);

F[][] aa1 = [a1, a1, a1];
F[][] aa2 = [a2, a2, a2];
ti = __typeid!(F[]);
assert(ti.getHash(&a1) == ti.getHash(&a2));

assert(aa1 == aa2);
assert(aa1 !is aa2);

ti = __typeid!(F[][]);
assert(ti.getHash(&aa1) == ti.getHash(&aa2));

S s1 = {f1},
s2 = {f2};
assert(s1 == s2);
assert(s1 !is s2);

S[] da1 = [S(f1), S(f1), S(f1)],
da2 = [S(f2), S(f2), S(f2)];

ti = __typeid!(S);
assert(ti.getHash(&s1) == ti.getHash(&s2));

assert(da1 == da2);
assert(da1 !is da2);

ti = __typeid!(S[]);
assert(ti.getHash(&da1) == ti.getHash(&da2));

S[3] sa1 = {f1},
sa2 = {f2};
assert(sa1 == sa2);
assert(sa1[] !is sa2[]);

ti = __typeid!(S[3]);
assert(ti.getHash(&sa1) == ti.getHash(&sa2));
}();

// imaginary types
foreach (F; TypeTuple!(ifloat, idouble, ireal))
(){ // workaround #2396
alias S = SX!F;
F f1 = +0.0i,
f2 = -0.0i;
F[] a1 = [f1, f1, f1];
F[] a2 = [f2, f2, f2];
assert(f1 == f2);
assert(f1 !is f2);
TypeInfo ti = __typeid!(F);
assert(ti.getHash(&f1) == ti.getHash(&f2));

assert(a1 == a2);
assert(a1 !is a2);

F[][] aa1 = [a1, a1, a1];
F[][] aa2 = [a2, a2, a2];

ti = __typeid!(F[]);
assert(ti.getHash(&a1) == ti.getHash(&a2));

assert(aa1 == aa2);
assert(aa1 !is aa2);
ti = __typeid!(F[][]);
assert(ti.getHash(&aa1) == ti.getHash(&aa2));

S s1 = {f1},
s2 = {f2};
assert(s1 == s2);
assert(s1 !is s2);

S[] da1 = [S(f1), S(f1), S(f1)],
da2 = [S(f2), S(f2), S(f2)];

ti = __typeid!(S);
assert(ti.getHash(&s1) == ti.getHash(&s2));

assert(da1 == da2);
assert(da1 !is da2);

ti = __typeid!(S[]);
assert(ti.getHash(&da1) == ti.getHash(&da2));

S[3] sa1 = {f1},
sa2 = {f2};
assert(sa1 == sa2);
assert(sa1[] !is sa2[]);

ti = __typeid!(S[3]);
assert(ti.getHash(&sa1) == ti.getHash(&sa2));
}();

// complex types
foreach (F; TypeTuple!(cfloat, cdouble, creal))
(){ // workaround #2396
alias S = SX!F;
F[4] f = [+0.0 + 0.0i,
+0.0 - 0.0i,
-0.0 + 0.0i,
-0.0 - 0.0i];

foreach (i, f1; f) foreach (j, f2; f) if (i != j)
{
F[] a1 = [f1, f1, f1];
F[] a2 = [f2, f2, f2];
assert(f1 == 0 + 0i);

assert(f1 == f2);
assert(f1 !is f2);
TypeInfo ti = __typeid!(F);
assert(ti.getHash(&f1) == ti.getHash(&f2));

assert(a1 == a2);
assert(a1 !is a2);

F[][] aa1 = [a1, a1, a1];
F[][] aa2 = [a2, a2, a2];

ti = __typeid!(F[]);
assert(ti.getHash(&a1) == ti.getHash(&a2));

assert(aa1 == aa2);
assert(aa1 !is aa2);

ti = __typeid!(F[][]);
assert(ti.getHash(&aa1) == ti.getHash(&aa2));

S s1 = {f1},
s2 = {f2};
assert(s1 == s2);
assert(s1 !is s2);

S[] da1 = [S(f1), S(f1), S(f1)],
da2 = [S(f2), S(f2), S(f2)];

ti = __typeid!(S);
assert(ti.getHash(&s1) == ti.getHash(&s2));

assert(da1 == da2);
assert(da1 !is da2);

S[3] sa1 = {f1},
sa2 = {f2};

ti = __typeid!(S[]);
assert(ti.getHash(&da1) == ti.getHash(&da2));

assert(sa1 == sa2);
assert(sa1[] !is sa2[]);

ti = __typeid!(S[3]);
assert(ti.getHash(&sa1) == ti.getHash(&sa2));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice coverage tests

}
}();
}