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