Thread overview
[Issue 21511] Uniqueness detection failed in non-template function with delegate parameter
Dec 29, 2020
Bolpat
Dec 29, 2020
ag0aep6g
Jan 02, 2021
Bolpat
December 29, 2020
https://issues.dlang.org/show_bug.cgi?id=21511

Bolpat <qs.il.paperinik@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |rejects-valid, safe
                 CC|                            |qs.il.paperinik@gmail.com

--
December 29, 2020
https://issues.dlang.org/show_bug.cgi?id=21511

ag0aep6g <ag0aep6g@gmail.com> changed:

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

--- Comment #1 from ag0aep6g <ag0aep6g@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.

--
January 02, 2021
https://issues.dlang.org/show_bug.cgi?id=21511

Bolpat <qs.il.paperinik@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |INVALID

--