Thread overview
[Issue 22792] Wrong inference of opApply
Dec 17, 2022
Iain Buclaw
February 20, 2022
https://issues.dlang.org/show_bug.cgi?id=22792

moonlightsentinel@disroot.org changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |moonlightsentinel@disroot.o
                   |                            |rg

--- Comment #1 from moonlightsentinel@disroot.org ---
> 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

--
February 20, 2022
https://issues.dlang.org/show_bug.cgi?id=22792

--- Comment #2 from moonlightsentinel@disroot.org ---
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
-----

--
February 20, 2022
https://issues.dlang.org/show_bug.cgi?id=22792

--- Comment #3 from moonlightsentinel@disroot.org ---
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) {}
}

--
February 20, 2022
https://issues.dlang.org/show_bug.cgi?id=22792

--- Comment #4 from moonlightsentinel@disroot.org ---
(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`).

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=22792

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P3

--
December 13
https://issues.dlang.org/show_bug.cgi?id=22792

--- Comment #5 from dlangBugzillaToGithub <robert.schadek@posteo.de> ---
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

--