Bug 22497 – Spurious dual-context error

Status
NEW
Severity
blocker
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-11-09T18:05:19Z
Last change time
2024-12-13T19:19:14Z
Assigned to
No Owner
Creator
Andrei Alexandrescu
See also
https://issues.dlang.org/show_bug.cgi?id=5710
Moved to GitHub: dmd#18065 →

Comments

Comment #0 by andrei — 2021-11-09T18:05:19Z
Consider: template canon(string v) { auto fun(alias lambda)(int x) { return lambda(x); } } alias f1 = canon!"abc".fun; void main() { int x = 42; f1!(y => y + x)(1); } The code produces the error: Deprecation: function `onlineapp.main.f1!((y) => y + x).fun` function requires a dual-context, which is deprecated There is no dual context anywhere in sight. The canon template takes a compile-time string, which requires no context. This blocks phobos versioning.
Comment #1 by kinke — 2021-11-10T14:30:58Z
AFAIK, the problem is that the alias template parameter doesn't capture the context if bound to a nested function, unlike a delegate runtime parameter. `canon!"abc".fun!<delegateLambda>` would need a hidden context runtime parameter to forward to the lambda invocation: auto canon!"abc".fun!<lambda>(void* __lambda_context, int x) { return <lambda>(__lambda_context, x); } void main() { int x = 42; canon!"abc".fun!(y => y + x)(<main_context>, 1); }
Comment #2 by andrei — 2021-11-10T17:45:54Z
(In reply to kinke from comment #1) > AFAIK, the problem is that the alias template parameter doesn't capture the > context if bound to a nested function, unlike a delegate runtime parameter. > `canon!"abc".fun!<delegateLambda>` would need a hidden context runtime > parameter to forward to the lambda invocation: > > auto canon!"abc".fun!<lambda>(void* __lambda_context, int x) { > return <lambda>(__lambda_context, x); > } > > void main() { > int x = 42; > canon!"abc".fun!(y => y + x)(<main_context>, 1); > } Not sure I understand but hopefully it's something that can be fixed, right? Things would be different if the template itself took an alias parameter that could be bound to a distinct context. But it being a string makes all the difference. Also forgot to mention that this code also doesn't work but for a different reason: template canon(string v) { static auto fun(alias lambda)(int x) { return lambda(x); } } alias f1 = canon!"abc".fun; void main() { int x = 42; f1!(y => y + x)(1); } Error: `static` function `onlineapp.main.f1!((y) => y + x).fun` cannot access delegate `__lambda2` in frame of function `D main`
Comment #3 by kinke — 2021-11-10T19:15:38Z
(In reply to Andrei Alexandrescu from comment #2) > Not sure I understand but hopefully it's something that can be fixed, right? Nevermind, that's what the compiler does for a freestanding function template. In your example with parent template instance, the current behavior seems to match that of a simple struct parent: ``` int foo(alias f)(int x) { return f(x); } struct S { static int staticFoo(alias f)(int x) { return f(x); } int foo(alias f)(int x) { return f(x); } } void main() { int x = 42; int nested(int y) { return y + x; } foo!nested(1); // should work analogously (without dual context) but doesn't: //S.staticFoo!nested(1); // correctly requires dual-context: S().foo!nested(1); } ``` So some logic seems to be definitely off here (and surely fixable).
Comment #4 by robert.schadek — 2024-12-13T19:19:14Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18065 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB