On Wednesday, 25 February 2015 at 20:36:33 UTC, Namespace wrote:
On Wednesday, 25 February 2015 at 20:15:10 UTC, anonymous wrote:
[...]
It may be possible to hack through this limitation - NOT
THOUGHT-OUT, NOT TESTED, NOT RECOMMENDED:
---
void glCheck(scope lazy int thing) @nogc;
pragma(mangle, glCheck.mangleof) void glCheckImpl(scope int
delegate() @nogc thing) @nogc {auto x = thing();}
int costly() @nogc {return 42;}
void main() @nogc
{
glCheck(costly());
int x; glCheck(x);
}
---
That last thing works. But I have no clue why. o.O
Anyway, thanks a lot!
I advise you to not use it. It's a hack that relies on
implementation details of the compiler.
As for how it works:
pragma(mangle, ...) sets the mangled name of the following
symbol. The mangled name is similar to the "fully qualified
name", but it includes parameter types and such. So different
overloads of a function have different mangled names, while
sharing one fully qualified name.
Giving glCheckImpl the same mangled name as glCheck means they
then refer to the same code despite having different signatures.
This bypasses the type system. DON'T DO THIS.
So, whenever glCheck is called, really glCheckImpl is called, and
the `scope lazy int` argument is interpreted as a `scope int
delegate() @nogc` argument.
This works, because currently the compiler creates delegates for
lazy arguments and calls those delegates when the arguments are
accessed. So right now, `lazy int` is the same as `int
delegate()` under the hood. But this is not guaranteed. The
compiler is free to do this differently. It may depend on
compiler flags, etc. SO DON'T DO THIS.