5
votes

Consider the following code:

module ftwr;

import std.regex;
import std.stdio;
import std.conv;
import std.traits;

S consume (S) (ref S data, Regex ! ( Unqual!(typeof(S.init[0])) ) rg)
{
    writeln (typeid(Unqual!(typeof(S.init[0]))));

    auto m = match(data, rg);
    return m.hit;
}

void main()
{
    auto data = "binary large object";
    auto rx = regex(".*");
    consume (data, rx); // this line is mentioned in the error message
}

Now, I expect the compiler to infer that consume is to be instantiated as

string consume!(string)(string, Regex!(char))

but that doesn't seem to happen. The errors are as follows:

func_template_with_regex.d(24): Error: template ftwr.consume(S) does not match any function template declaration
func_template_with_regex.d(24): Error: template ftwr.consume(S) cannot deduce template function from argument types !()(string,Regex!(char))

and I see that the parameter types are correct... I've tried some variations of function signature, like:

S consume (S) (Regex ! ( Unqual!(typeof(S.init[0])) ) rg, ref S data)

which doesn't compile also (the idea was to change the order of arguments), and

immutable(S)[] consume (S) (Regex ! ( S ) rg, ref immutable(S)[] data)

which compiles and infers the types alright. If I specify the type explicitly in the call, i.e.

consume!string(data, rx);

it also compiles and the debug writeln prints char, just as expected. Am I missing something in the inference rules, or I've just hit a bug in the compiler?

Oh yes:

$ dmd -v
DMD64 D Compiler v2.053
...
1
It might be that it can't infer anything from the second argument (it's too complicated), so it just doesn't infer. - user541686
@Mehrdad: I imagine "type inference" as process of solving some equation system. If it's right (?), then, any "type too complex for inference" is just an equation with insufficient data. But it seems like the system is pretty solvable... (I suppose so because there is a direct S data there, which is the solution itself) - vines
Well it's not like computers can solve any equation system algebraically, so it might be the same issue here. That said, I'm not saying it's not possible to optimize for this case -- it's quite possible. - user541686

1 Answers

5
votes

I can't say if it's a bug, but here's a workaround which doesn't force you to specify the type or change the order of arguments. Change consume's signature to:

S consume (S, U) (ref S data, Regex!U rg) if (is(U == Unqual!(typeof(S.init[0]))))