5

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
...
vines
  • 5,160
  • 1
  • 27
  • 49
  • It might be that it can't infer anything from the second argument (it's too complicated), so it just doesn't infer. – user541686 Jun 21 '11 at 15:14
  • @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 Jun 21 '11 at 15:20
  • 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 Jun 21 '11 at 15:34

1 Answers1

5

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]))))
Vladimir Panteleev
  • 24,651
  • 6
  • 70
  • 114
  • That's essentially what I was going to say to do, though adding `isSomeString!S` to the template constraint would be a good idea as well. It may be worth reporting this particular case in bugzilla ( d.puremagic.com/issues ) anyway, since it does appear to be an area where the compiler's type inference could be improved. But a cleaner function signature with template constraints works quite well as it is. Oh, and `data[0]` could be used instead of `S.init[0]` to clean up the constraint a bit more. – Jonathan M Davis Jun 21 '11 at 22:08
  • @Jonathan M Davis: `isSomeString!S` is what I was going to add next, as soon as the whole thing would get compiled :) – vines Jun 22 '11 at 10:16