Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

distinguish opApply overload on ref #19529

Open
dlangBugzillaToGithub opened this issue Jan 19, 2019 · 0 comments
Open

distinguish opApply overload on ref #19529

dlangBugzillaToGithub opened this issue Jan 19, 2019 · 0 comments

Comments

@dlangBugzillaToGithub
Copy link

Bolpat reported this on 2019-01-19T21:01:11Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=19597

Description

When opApply overloads are considered for foreach resolution, that have different ref-ness, the better match should be taken.
Currently, the compiler issues an ambiguity error.

There are two cases: When inferring the iteration variable type, and with explicit types on the iteration variable.

The case for inference:

struct Test
{
    const(int*) ptr;
    
    int opApply(scope int delegate(const(int)*) callback)
    {
        return callback(ptr);
    }
    int opApply(scope int delegate(ref const(int*)) callback)
    {
        return callback(ptr);
    }
}

void main()
{
    Test t = Test(new const int(1));
    foreach (p; t)
    {
        pragma(msg, typeof(p)); // should be const(int)*
        pragma(msg, __traits(isRef, p)); // should be false
    }
    
    foreach (ref p; t)
    {
        pragma(msg, typeof(p)); // should be const(int*)
        pragma(msg, __traits(isRef, p)); // should be true
    }
}

Making the types explicit solves this because the types aren't exactly the same.

For explicit types on the iteration variable, change the first opApply overload to take const(int*). The compiler issues an ambiguity error while there is clearly a better overload for each of them. Calling opApply directly works:

struct Test
{
    const(int*) ptr;
    int opApply(scope int delegate(const(int*)) callback)
    {
        return callback(ptr);
    }
    int opApply(scope int delegate(ref const(int*)) callback)
    {
        return callback(ptr);
    }
}

void main()
{
    t.opApply((const(int*) p)
    {
        pragma(msg, typeof(p)); // should be const(int*)
        pragma(msg, __traits(isRef, p)); // should be false
        return 0;
    });
    
    t.opApply((ref const(int*) p)
    {
        pragma(msg, typeof(p)); // should be const(int*)
        pragma(msg, __traits(isRef, p)); // should be true
        return 0;
    });
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant