More fun with autodecoding
Steven Schveighoffer
schveiguy at gmail.com
Tue Sep 11 13:06:12 UTC 2018
On 9/10/18 1:44 PM, Andrei Alexandrescu wrote:
> On 9/10/18 12:46 PM, Steven Schveighoffer wrote:
>> On 9/10/18 8:58 AM, Steven Schveighoffer wrote:
>>> I'll have to figure out why my specialized range doesn't allow
>>> splitting based on " ".
>>
>> And the answer is: I'm an idiot. Forgot to define empty :) Also my
>> slicing operator accepted ints and not size_t.
>
> I guess a better error message would be in order.
>
A better error message would help prevent the painful diagnosis that I
had to do to actually find the issue.
So the error I got was this:
source/bufref.d(346,36): Error: template
std.algorithm.iteration.splitter cannot deduce function from argument
types !()(Result, string), candidates are:
/Users/steves/.dvm/compilers/dmd-2.081.0/osx/bin/../../src/phobos/std/algorithm/iteration.d(3792,6):
std.algorithm.iteration.splitter(alias pred = "a == b", Range,
Separator)(Range r, Separator s) if (is(typeof(binaryFun!pred(r.front,
s)) : bool) && (hasSlicing!Range && hasLength!Range ||
isNarrowString!Range))
/Users/steves/.dvm/compilers/dmd-2.081.0/osx/bin/../../src/phobos/std/algorithm/iteration.d(4163,6):
std.algorithm.iteration.splitter(alias pred = "a == b", Range,
Separator)(Range r, Separator s) if (is(typeof(binaryFun!pred(r.front,
s.front)) : bool) && (hasSlicing!Range || isNarrowString!Range) &&
isForwardRange!Separator && (hasLength!Separator ||
isNarrowString!Separator))
/Users/steves/.dvm/compilers/dmd-2.081.0/osx/bin/../../src/phobos/std/algorithm/iteration.d(4350,6):
std.algorithm.iteration.splitter(alias isTerminator,
Range)(Range r) if (isForwardRange!Range &&
is(typeof(unaryFun!isTerminator(r.front))))
/Users/steves/.dvm/compilers/dmd-2.081.0/osx/bin/../../src/phobos/std/algorithm/iteration.d(4573,6):
std.algorithm.iteration.splitter(C)(C[] s) if (isSomeChar!C)
This means I had to look at each line, figure out which overload I'm
calling, and then copy all the constraints locally, seeing which ones
were true and which ones false.
But it didn't stop there. The problem was hasSlicing!Range. If you look
at hasSlicing, it looks like this:
enum bool hasSlicing(R) = isForwardRange!R
&& !isNarrowString!R
&& is(ReturnType!((R r) => r[1 .. 1].length) == size_t)
&& (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
&& (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 ..
$]) == R))
&& (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
|| is(typeof(lvalueOf!R[0 .. $ - 1]) == R))
&& is(typeof((ref R r)
{
static assert(isForwardRange!(typeof(r[1 .. 2])));
}));
Now I had to instrument a whole slew of items. I pasted this whole thing
this into my code, added an alias to my range type for R, and then
changed the big boolean expression to a bunch of static asserts.
Then I found the true culprit was isForwardRange!R. This led me to
requestion my sanity, and finally realized I forgot the empty function.
A fabulous fantastic mechanism that would have saved me some time is
simply coloring the clauses of the template constraint that failed red,
the ones that passed green, and the ones that weren't evaluated grey.
Furthermore, it would be good to either recursively continue this for
red clauses like `hasSlicing` which have so much underneath. Either that
or a way to trigger the colored evaluation on demand.
If I were a dmd guru, I'd look at doing this myself. I may still try and
hack it in just to see if I can do it.
------
Finally, there is a possible bug in the definition of hasSlicing: it
doesn't require the slice parameters be size_t, but there are places
(e.g. inside std.algorithm.searching.find) that pass in range.length ..
range.length for slicing the range. In my implementation I had used ints
as the parameters for opSlice. So I started seeing errors deep inside
std.algorithm saying there was no overload for slicing. Again the sanity
was questioned, and I figured out the error and now it's actually working.
-Steve
More information about the Digitalmars-d
mailing list