www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 21683] New: ref/non-ref opApply overloads used in foreach

https://issues.dlang.org/show_bug.cgi?id=21683

          Issue ID: 21683
           Summary: ref/non-ref opApply overloads used in foreach loops
                    are ambiguous
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: blocker
          Priority: P3
         Component: dmd
          Assignee: nobody puremagic.com
          Reporter: dlang-bugzilla thecybershadow.net

/////////////////////////////// test.d //////////////////////////////
void main()
{
    // D AAs auto-infer constness of the key, based on whether "ref"
    // iteration was requested or not:
    bool[int] aa;
    foreach (k, v; aa)
        pragma(msg, typeof(k)); // int
    foreach (ref k, v; aa)
        pragma(msg, typeof(k)); // const(int)

    // However, attempting to implement the same behavior in a custom
    // type does not appear to be possible.

    struct S
    {
        // One would think that the compiler would pick the
        // appropriate overload, based on whether ref is requested
        // or not:
        int opApply(int delegate(          int, bool));
        int opApply(int delegate(ref const int, bool));
    }
    S s;

    // However, the following simply fails with an ambiguity error:
    foreach (k, v; s) {}
}
/////////////////////////////////////////////////////////////////////

Compiler output:

int
const(int)
test.d(25): Error: `s.opApply` matches more than one declaration:
`test.d(19)`:     `int(int delegate(int, bool))`
and:
`test.d(20)`:     `int(int delegate(ref const(int), bool))`
test.d(25): Error: cannot uniquely infer `foreach` argument types


This blocks wrapping native D AAs into custom types, or creating custom AA
implementations.

--
Mar 06 2021