Bug 23116 – foreach with opApply infer ref when opApply delegate is templated

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2022-05-16T16:43:48Z
Last change time
2024-12-13T19:22:50Z
Keywords
pull
Assigned to
No Owner
Creator
Luís Ferreira
Moved to GitHub: dmd#20104 →

Comments

Comment #0 by contact — 2022-05-16T16:43:48Z
For the following code: ``` struct S { int opApply(Dg)(scope Dg dg) { return dg(1); } } int main() { foreach(int i; S()) { return i; } return 0; } ``` The compiler interprets this as: ``` foreach(ref int i; S()) ``` Which is wrongly inferred.
Comment #1 by dlang-bot — 2022-05-16T16:48:11Z
@ljmf00 created dlang/dmd pull request #14132 "fix(statementsem): foreach shouldn't infer ref on templated opApply" fixing this issue: - fix(statementsem): foreach shouldn't infer ref on templated opApply When a foreach with templated opApply, the compiler infers the following: ```d foreach(ref int i; S()) ``` Even if you explicitly type it as non-ref. Fix issue 23116. Reference: https://issues.dlang.org/show_bug.cgi?id=23116 Signed-off-by: Luís Ferreira <[email protected]> https://github.com/dlang/dmd/pull/14132
Comment #2 by dkorpel — 2022-05-16T17:22:55Z
Does inferring ref result in actual behavioral problems?
Comment #3 by contact — 2022-05-16T17:28:41Z
(In reply to Dennis from comment #2) > Does inferring ref result in actual behavioral problems? It is. It should use the available overload. In my case, I have something like: ``` [ParameterStorageClassTuple!Dg].all!(stc => !(stc & STC.ref_)) ``` It should fall into the usable case, like it does without templating it.
Comment #4 by contact — 2022-05-16T17:55:10Z
Doing fallback of the overload manually can be a workaround for this: ``` int opApply(Dg : int delegate(ref ubyte))(scope Dg dg) { enum attrs = functionAttributes!Dg; alias nonRefDg = SetFunctionAttributes!(int delegate(ubyte), functionLinkage!Dg, attrs); foreach(ubyte i; &this.opApply!(nonRefDg)) // use the correct overload if(auto ret = dg(i)) return ret; return 0; } int opApply(Dg : int delegate(ubyte))(scope Dg dg) { // ... } ```
Comment #5 by contact — 2022-05-16T18:48:49Z
Ok, I found the problem. The compiler seem to choose right for function declarations, but there is no logic for template declarations: https://github.com/dlang/dmd/blob/master/src/dmd/opover.d#L1598
Comment #6 by dlang-bot — 2024-06-26T16:49:28Z
@Bolpat created dlang/dlang.org pull request #3859 "Specify `opApply` as an alias to a function template instance" fixing this issue: - Fix Bugzilla Issues 23666, 17953, 23116, and 24633 https://github.com/dlang/dlang.org/pull/3859
Comment #7 by robert.schadek — 2024-12-13T19:22:50Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/20104 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB