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

Commit c45aca0

Browse files
Geod24MoonlightSentinel
authored andcommitted
Implement tuple-compatible _d_assert_fail2
The goal of this new hook is to superseed the current hook, but since there is an inter-dependence between DMD and druntime, we just introduce a new symbol and will remove the old one in a future PR after DMD has been adapted.
1 parent 09ddfff commit c45aca0

File tree

1 file changed

+56
-15
lines changed

1 file changed

+56
-15
lines changed

src/core/internal/dassert.d

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,27 +47,50 @@ string _d_assert_fail(string comp, A, B)(auto ref const scope A a, auto ref cons
4747
* Returns:
4848
* A string such as "$a != true" or "$a == true".
4949
*/
50+
string _d_assert_fail2(A)(string op, auto ref const scope A a)
51+
{
52+
string[2] vals = [ miniFormatFakeAttributes(a), "true" ];
53+
immutable token = op == "!" ? "==" : "!=";
54+
return combine(vals[0 .. 1], token, vals[1 .. $]);
55+
}
56+
57+
/// Ditto
5058
string _d_assert_fail(A)(const scope string op, auto ref const scope A a)
5159
{
52-
string val = miniFormatFakeAttributes(a);
60+
string[2] vals = [ miniFormatFakeAttributes(a), "true" ];
5361
immutable token = op == "!" ? "==" : "!=";
54-
return combine(val, token, "true");
62+
return combine(vals[0 .. 1], token, vals[1 .. $]);
5563
}
5664

5765
/**
5866
* Generates rich assert error messages for binary expressions
5967
*
6068
* The binary expression `assert(x == y)` will be turned into
61-
* `assert(x == y, _d_assert_fail("==", x, y))`.
69+
* `assert(x == y, _d_assert_fail!(typeof(x))("==", x, y))`.
6270
*
6371
* Params:
6472
* comp = Comparison operator that was used in the expression.
65-
* a = Left hand side operand.
66-
* b = Right hand side operand.
73+
* a = Left hand side operand (can be a tuple).
74+
* b = Right hand side operand (can be a tuple).
6775
*
6876
* Returns:
6977
* A string such as "$a $comp $b".
7078
*/
79+
template _d_assert_fail2(A...) {
80+
string _d_assert_fail2(B...)(
81+
string comp, auto ref const scope A a, auto ref const scope B b)
82+
{
83+
string[A.length + B.length] vals;
84+
static foreach (idx; 0 .. A.length)
85+
vals[idx] = miniFormatFakeAttributes(a[idx]);
86+
static foreach (idx; 0 .. B.length)
87+
vals[A.length + idx] = miniFormatFakeAttributes(b[idx]);
88+
immutable token = invertCompToken(comp);
89+
return combine(vals[0 .. A.length], token, vals[A.length .. $]);
90+
}
91+
}
92+
93+
/// Ditto
7194
string _d_assert_fail(A, B)(const scope string comp, auto ref const scope A a, auto ref const scope B b)
7295
{
7396
/*
@@ -77,26 +100,44 @@ string _d_assert_fail(A, B)(const scope string comp, auto ref const scope A a, a
77100
Hence, we can fake purity and @nogc-ness here.
78101
*/
79102

80-
string valA = miniFormatFakeAttributes(a);
81-
string valB = miniFormatFakeAttributes(b);
103+
string[1] valA = miniFormatFakeAttributes(a);
104+
string[1] valB = miniFormatFakeAttributes(b);
82105
immutable token = invertCompToken(comp);
83-
return combine(valA, token, valB);
106+
return combine(valA[], token, valB[]);
84107
}
85108

86109
/// Combines the supplied arguments into one string "valA token valB"
87-
private string combine(const scope string valA, const scope string token,
88-
const scope string valB) pure nothrow @nogc @safe
110+
private string combine(const scope string[] valA, const scope string token,
111+
const scope string[] valB) pure nothrow @nogc @safe
89112
{
90-
const totalLen = valA.length + token.length + valB.length + 2;
113+
// Each separator is 2 chars (", "), plus the two spaces around the token.
114+
size_t totalLen = (valA.length - 1) * 2 +
115+
(valB.length - 1) * 2 + 2 + token.length;
116+
foreach (v; valA) totalLen += v.length;
117+
foreach (v; valB) totalLen += v.length;
91118
char[] buffer = cast(char[]) pureAlloc(totalLen)[0 .. totalLen];
92119
// @nogc-concat of "<valA> <comp> <valB>"
93-
auto n = valA.length;
94-
buffer[0 .. n] = valA;
120+
static void formatTuple (scope char[] buffer, ref size_t n, in string[] vals)
121+
{
122+
foreach (idx, v; vals)
123+
{
124+
if (idx)
125+
{
126+
buffer[n++] = ',';
127+
buffer[n++] = ' ';
128+
}
129+
buffer[n .. n + v.length] = v;
130+
n += v.length;
131+
}
132+
}
133+
134+
size_t n;
135+
formatTuple(buffer, n, valA);
95136
buffer[n++] = ' ';
96137
buffer[n .. n + token.length] = token;
97138
n += token.length;
98139
buffer[n++] = ' ';
99-
buffer[n .. n + valB.length] = valB;
140+
formatTuple(buffer, n, valB);
100141
return (() @trusted => cast(string) buffer)();
101142
}
102143

@@ -371,7 +412,7 @@ private string invertCompToken(string comp) pure nothrow @nogc @safe
371412
case "!in":
372413
return "in";
373414
default:
374-
assert(0, combine("Invalid comparison operator", "-", comp));
415+
assert(0, combine(["Invalid comparison operator"], "-", [comp]));
375416
}
376417
}
377418

0 commit comments

Comments
 (0)