This should compile:
----
struct S { int field; }
bool ft(alias ignored)() { return true; }
alias f = ft!(S.field); /* accepted */
enum e = f(); /* Error: need 'this' for 'ft' of type 'bool()' */
----
Works when `ft` is marked as `static`, which should be a NOP:
----
struct S { int field; }
static bool ft(alias ignored)() { return true; }
alias f = ft!(S.field);
enum e = f(); /* no error */
----
Curiously, taking a function pointer and calling it also works, but only at run time and only when done in two steps:
----
struct S { int field; }
bool ft(alias ignored)() { return true; }
alias f = ft!(S.field);
void main()
{
bool function() fptr = &f; /* accepted */
assert(fptr()); /* accepted and passes */
/+ These fail; should all work:
assert(f()); /* Error: need 'this' for 'ft' of type 'pure nothrow @nogc @safe bool()' */
assert((&f)()); /* ditto */
static bool function() fptr2 = &f; /* Error: non-constant expression & ft */
+/
}
----
Related thread in D.learn: http://forum.dlang.org/post/[email protected]
Comment #1 by dlang-bugzilla — 2017-05-26T03:56:41Z
(In reply to ag0aep6g from comment #0)
> This should compile:
AFAIU, detecting whether an alias parameter should be passed with context or not is a difficult problem because it changes the function's mangling and ABI signature.
> Works when `ft` is marked as `static`, which should be a NOP:
Here static applies to the template, not function. You can observe this by explicitly rewriting the function template into an eponymous template.
> Curiously, taking a function pointer and calling it also works
It looks like you found a different bug here. A function template that takes an alias parameter can be implicitly cast to a function pointer, even when it uses the alias parameter:
---
struct S { int field; }
int ft(alias a)() { return a; }
alias f = ft!(S.field);
void main()
{
int function() fptr = &f; /* accepted */
int i = fptr(); /* accepted and passes */
}
---
The above compiles and segfaults at runtime.
That should be filed as a separate accepts-invalid bug.
Comment #2 by ag0aep6g — 2017-05-26T14:41:21Z
(In reply to Vladimir Panteleev from comment #1)
> Here static applies to the template, not function. You can observe this by
> explicitly rewriting the function template into an eponymous template.
In the code I showed, `static` applies to the template, yes. But applying it to the function also makes the code compile. And it should be a NOP either way. At least as far as I know. In the language, there's no such thing as a static module-level function/template that's distinct from a non-static module-level function/template, or is there?
[...]
> It looks like you found a different bug here. A function template that takes
> an alias parameter can be implicitly cast to a function pointer, even when
> it uses the alias parameter:
[...]
> That should be filed as a separate accepts-invalid bug.
Sure. Issue 17439.
Comment #3 by dlang-bugzilla — 2017-05-26T14:53:06Z
(In reply to Vladimir Panteleev from comment #3)
> If a template has an alias parameter, the template becomes nested inside the
> same context as the alias argument's context. E.g. if the alias argument is
> a local variable inside a function, the template becomes nested in that
> function, i.e. acts as if it was declared inside the function's body.
Makes sense.
> "static" here has the same effect as on symbols inside function bodies or
> aggregate types: they force the compiler to not create a context pointer.
That sounds reasonable, but it needs a paragraph in the spec. Or is it in there and I just can't find it?
If that kind of `static` gets (or is) defined in the spec, this issue could be closed as invalid on the grounds that the "static" version is the correct way to write the code.
Comment #6 by snarwin+bugzilla — 2023-02-24T15:32:35Z
*** Issue 23738 has been marked as a duplicate of this issue. ***
Comment #7 by robert.schadek — 2024-12-13T18:52:18Z