Hi,

I was working with std.concurrency and discovered a (now reported) bug about receive and function. It lead me to some experimentations with fucntions. consider the code bellow :

module funtest;

import std.stdio;

void infos(T)(T fun) {
        writeln(typeof(fun).stringof);
        writeln("is function ? : ", is(T == function)); // Always false
writeln("is delegate ? : ", is(T == delegate)); // true if we have a delegate
}

int doNothing() { return 0; }

void main() {
infos(doNothing); // Evaluate even if it isn't @property . Expected behaviour ?
        infos(&doNothing);
        auto fun = &doNothing; infos(&fun);
        infos(function int() { return 0; });
        infos(delegate int() { return 0; });
        infos(() { return 0; }); // Delegate ??
}

And its output :

int
is function ? : false
is delegate ? : false
int function()
is function ? : false
is delegate ? : false
int function()*
is function ? : false
is delegate ? : false
int function() pure nothrow @safe
is function ? : false
is delegate ? : false
int delegate() pure nothrow @safe
is function ? : false
is delegate ? : true
int delegate() pure nothrow
is function ? : false
is delegate ? : true

Now some strange stuff happens. I wonder if they all are intended. First of all, in the first case, doNothing is evaluated, even with no () . This function isn't @property, so this behaviour is somehow misleading and error prone.

When passing a delegate, is(T == delegate) is true, but when passing a function is(T == function) is false. This is also misleading and inconsistent. This lead to the bugs in std.concurrency I faced.

When it is not specifiate if something is a delegate or a function, the compiler always makes it a delegate. Is it intended ? This can create some overhead in many cases for nothing. Plus, this si always possible to wrap a function into a delegate, but the other way around isn't possible. So the compiler should do its best to make a function whatever can be one.

Even if it is not in the code snippet, typeof(doNothing).stringof is int() . When doNothing is passed, it is evaluated, and we get an int. Theses 2 results are counter intuitives, and this is a types of things that we want to avoid in D.

So, what is a bug ? What is an expected behaviour ? What isn't defined/decided yet ? And what do we decide if it is so ?

Reply via email to