[Issue 21511] Uniqueness detection failed in non-template function with delegate parameter

d-bugmail at puremagic.com d-bugmail at puremagic.com
Tue Dec 29 15:11:04 UTC 2020


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

ag0aep6g <ag0aep6g at gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ag0aep6g at gmail.com

--- Comment #1 from ag0aep6g <ag0aep6g at gmail.com> ---
(In reply to Bolpat from comment #0)
> immutable(int)* g(const scope int* delegate() pure @safe dg) @safe
> {
>     return dg(); // error
> }
> 
> immutable(int)* h(DG)(const scope DG dg) @safe
>     // just to be sure nothing surprising happens:
>     if (is(DG == int* delegate() pure @safe))
> {
>     return dg(); // okay
> }
> 
> The reason why the result of calling the function pointer or delegate are
> valid, is due to uniqueness.[1] Especially weird is the fact that h lowers
> to g after the template parameter is determined (only one option).
[...]
> [1] https://dlang.org/spec/const3.html#creating_immutable_data

There is a significant difference between g and h: g isn't `pure`. h is.

The issue can be summarized like this:

    immutable(int)* foo(const scope int* delegate() pure @safe dg) pure @safe
    {
        immutable int* i = dg(); /* error (line A) */
        return dg(); /* no error (line B) */
    }

The heart of the problem is that delegates offer a head const mechanism. `dg`
can return a pre-existing mutable int* from its context. It's not guaranteed to
be unique. Example:

    class C
    {
        int x;
        int* method() pure @safe { return &x; }
    }
    void main()
    {
        auto c = new C;
        const int* delegate() dg = &c.method;
        int* p = dg(); /* no error; not a unique reference (line C) */
    }

Such a `dg()` cannot be allowed to implicitly convert to immutable. The
compiler recognizes that when it rejects line A, but it misses line B.

We can either:

1) disallow line B, or
2) make `const` on delegates transitive, consequently allowing line A and
disallowing line C.

--


More information about the Digitalmars-d-bugs mailing list