Bug 22792 – Wrong inference of opApply

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2022-02-19T06:03:30Z
Last change time
2024-12-13T19:21:01Z
Assigned to
No Owner
Creator
SHOO
Moved to GitHub: dmd#20055 →

Comments

Comment #0 by zan77137 — 2022-02-19T06:03:30Z
Why is following code different behavior between int and string? ----------------- import std; struct S { int opApply(int delegate(ref const(int), ref int) dg) { writeln("mutable int"); return 0; } int opApply(int delegate(ref const(int), ref const(int)) dg) const { writeln("const int"); return 0; } int opApply(int delegate(ref const(int), ref string) dg) { writeln("mutable str"); return 0; } int opApply(int delegate(ref const(int), ref const(string)) dg) const { writeln("const str"); return 0; } } void main() { S s; foreach (ref const(int) x, ref const(int) y; s) {} foreach (ref const(int) x, ref const(string) y; s) {} } ----------------- rdmd playground.d const int mutable str ----------------- The function on the const one that matches better should be called. This problem was discovered by investigating the cause of Botan(*) build failure in 2.099.1-beta.1. However, the above code shows the same behavior since before 2.098.1. * https://github.com/etcimon/botan
Comment #1 by moonlightsentinel — 2022-02-20T12:02:11Z
> The function on the const one that matches better should be called. Neither of the string opApply's is an exact match due to the const missmatch on `this` or the delegate parameter => "match with implicit conversions". Partial ordering then selects the mutable overload because it is "more specialized" (cannot be called by the const overload). Not sure why the int overloads expose a different behaviour. See https://dlang.org/spec/function.html#function-overloading
Comment #2 by moonlightsentinel — 2022-02-20T12:03:07Z
Slightly modified test case: import core.stdc.stdio; struct S { int opApply(int delegate(ref const(int), ref int) dg) { puts("mutable int"); return 0; } int opApply(int delegate(ref const(int), ref const(int)) dg) const { puts("const int"); return 0; } int opApply(int delegate(ref const(int), ref string) dg) { puts("mutable str"); return 0; } int opApply(int delegate(ref const(int), ref const(string)) dg) const { puts("const str"); return 0; } } void main() { S s; foreach (ref const(int) x, ref const(int) y; s) {} foreach (ref const(int) x, ref const(string) y; s) {} const S s2; foreach (ref const(int) x, ref const(int) y; s2) {} foreach (ref const(int) x, ref const(string) y; s2) {} } Up to 2.074.1: Success with output: ----- const int const str const int const str ----- Since 2.075.1: Success with output: ----- const int mutable str const int const str -----
Comment #3 by moonlightsentinel — 2022-02-20T12:17:41Z
Same behaviour without the first parameter that is identical for every overload: struct S { int opApply(int delegate(ref int) dg) { puts("mutable int"); return 0; } int opApply(int delegate(ref const(int)) dg) const { puts("const int"); return 0; } int opApply(int delegate(ref string) dg) { puts("mutable str"); return 0; } int opApply(int delegate(ref const(string)) dg) const { puts("const str"); return 0; } } void main() { S s; foreach (ref const(int) y; s) {} foreach (ref const(string) y; s) {} const S s2; foreach (ref const(int) y; s2) {} foreach (ref const(string) y; s2) {} }
Comment #4 by moonlightsentinel — 2022-02-20T12:21:24Z
(In reply to moonlightsentinel from comment #1) > [...] "match with implicit conversions". Correction: This applies only to the mutable overload because the delegate type changes due to the different constness. The const overload should be "match with qualifier conversion" (`S` => `const S`).
Comment #5 by robert.schadek — 2024-12-13T19:21:01Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/20055 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB