Bug 17435 – bogus "need 'this'" error with aggregate field passed in alias parameter

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2017-05-25T20:39:37Z
Last change time
2024-12-13T18:52:18Z
Keywords
rejects-valid
Assigned to
No Owner
Creator
ag0aep6g
Moved to GitHub: dmd#19254 →

Comments

Comment #0 by ag0aep6g — 2017-05-25T20:39:37Z
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 ag0aep6g from comment #2) > 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? 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. "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. I've discussed this topic at this DConf a bit. Some additional links: https://github.com/D-Programming-Language/dmd/pull/2794 https://github.com/D-Programming-Language/dmd/pull/3884 https://github.com/D-Programming-Language/dmd/pull/3345 https://issues.dlang.org/show_bug.cgi?id=11946 https://issues.dlang.org/show_bug.cgi?id=7805 https://github.com/CyberShadow/ae/blob/master/utils/meta/caps.d
Comment #4 by dlang-bugzilla — 2017-05-26T14:54:11Z
(In reply to Vladimir Panteleev from comment #3) > Some additional links: https://wiki.dlang.org/Brush_Up_Language_Features#Nested_Symbols
Comment #5 by ag0aep6g — 2017-05-26T15:08:42Z
(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
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19254 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB