[Issue 10850] Inout substituted incorrectly for delegates/fptrs in inout function signature

via Digitalmars-d-bugs digitalmars-d-bugs at puremagic.com
Sat Sep 13 11:11:03 PDT 2014


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

timon.gehr at gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|normal                      |major

--- Comment #3 from timon.gehr at gmx.ch ---
(In reply to Sobirari Muhomori from comment #2)
> (In reply to timon.gehr from comment #0)
> > git head:
> > 
> > Since apparently inout now refers to the outermost inout function
> 
> What? How? That looks incorrect.

What are you referring to? The current behaviour of DMD is indeed to consider
'inout' bound to the outermost inout function signature, this is why the
following code does not compile:

void foo(ref inout(int) x){
    inout(int)* bar(inout(int)*) { return &x; }
    int y;
    bar(&y); // error
}


> inout should be applied to data passed to
> the inout function, not to delegate signatures, those are independent.
> ...

Well, no they are not.

It appears that DMD has been changed in the meantime to treat inout within
delegate signatures within function/delegate signatures as 'const'. However,
this is unsound:

inout(int)** delegate(inout int) foo(inout(int)** x){
    inout(int)** bar(inout int){ return x; }
    return &bar;
}

void main(){
    immutable(int) x;
    immutable(int)* ipx=&x;
    immutable(int)** ippx=&ipx;
    const(int)** cppx=foo(ippx)(2);
    int y=3; int* py=&y;
    *cppx=py;
    ipx=*ippx;
    assert(ipx is &y);
    static assert(is(typeof(*ipx)==immutable));
    assert(*ipx==3);
    y=4;
    assert(*ipx==4);
}

Increasing importance to major, because this issue causes type unsoundness.

> > should also be substituted for delegates inside the function signature:
> > 
> > inout(int)* delegate(inout(int)*) foo(ref inout(int) x){
> >     inout(int)* bar(inout(int)*) { return &x; }
> >     return &bar;
> > }
> 
> If one wants a really really stupid fix for nested inout functions, then
> inout data outside of the nested function should be treated as const.
> ...

All of these ad-hoc fixes are of a certain minimum stupidity because there is
no right answer here (more precisely, the 'right' answer would need to change
the surface syntax, because there would need to be more than one inout
qualifier). This report is assuming that the fix that Kenji Hara implemented in
DMD is the official fix.

In any case, this suggestion (as I understand it) is indeed particularly stupid
as it is unsound:

const(int)** foo(inout(int)** x){
    // inout treated as const from nested context:
    const(int)** bar(){ return x; }
    return bar();
}

(This is the same type coercion underlying the previous proof of unsoundness.)

> > immutable(int) x;
> > static assert(is(typeof(foo(x))==immutable(int)* delegate(immutable(int)*)));
> 
> I'd say, the return type should be inout delegate, converting it to
> immutable is possible, but unnecessarily restrictive.
> ...

Unnecessary how?

inout(int)* delegate(inout(int)*) foo(ref inout(int) x){
    inout(int)* bar(inout(int)*) { return &x; }
    return &bar;
}

void main(){
    immutable(int) x=2;
    auto dg=cast(inout(int)* delegate(inout(int)*))foo(x);
    int y;
    assert(dg(&y) is &x);
    *dg(&y)=3; // modification of immutable data
    assert(x!=*&x); // passes with DMD 2.066.0
}

I.e. everything else staying the same, the typing rules you propose are still
unsound.

> 
> assert(foo(&a,x=>x) is &a); looks like duplicate of issue 11772 (works for
> function, but not for delegate)

If anything, then issue 11772 is the duplicate.

--


More information about the Digitalmars-d-bugs mailing list