May 25, 2016
https://issues.dlang.org/show_bug.cgi?id=9149

--- Comment #11 from timon.gehr@gmx.ch ---
(In reply to Steven Schveighoffer from comment #10)
> I think the delegate assignment should be legal. The auto-conversion from pure ctor to immutable should be illegal (note that converting to const is not a good test case, because you can easily assign an A to a const A without purity), because casting the A to immutable does not affect the 'this' pointer of the delegate member, and that could point at the given object that you are casting or any member.

There might be a misunderstanding about what this report is about.

> I had thought that the 'this'
> pointer was const-agnostic. That is:
> 
> class C
> {
>    void foo() {}
>    void ifoo() immutable {}
> }
> 
> void main()
> {
>    mc = new C;
>    ic = new C;
>    void delegate() x = &mc.foo;
>    x = &mc.ifoo; // why not?
> }
> 
> Why does it matter if x's delegate has an immutable 'this'? that detail is insignificant to the caller.

I assume this is the code you intended to write:

void main(){
    auto mc=new C,ic=new immutable(C);
    void delegate() x = &mc.foo;
    x = &ic.ifoo; // why not?
}

DMD disallows this code. (Hopefully. I have checked multiple times :-).)
It is always okay to remove guarantees on the 'this' pointer, such as pure,
const or immutable, because the closure data is untyped (you can access it only
as a void*), so this should indeed be fine. You might consider opening an issue
about this.


This report is about the converse case.

The trouble is that the conversion delegate() -> const(delegate()) breaks
transitivity of const if we are allowed to call the const(delegate())
afterwards. I.e. if delegate() -> const(delegate()) conversion and calling
const(delegate())'s is allowed, and we have a function

void foo(const C c)pure{ ... }

then this function might modify state reachable by its argument. However, const is designed to guarantee this cannot happen: Code should not be able to modify data through a const reference (no matter whether the type system is able to prove that it was mutable originally).

import std.stdio;
@safe:
class C{
    int x=0;
    this(){ mthis=unconstify(this); }
    void mutate()const pure{ mthis.x++; }
private:
    const(Unconstify!C) mthis;
}

void foo(const C c)pure{
    c.mutate();
}

void main(){
    auto c=new C;
    auto x1=c.x;
    foo(c);
    auto x2=c.x;
    writeln(x1," ",x2); // 0 1
}


struct Unconstify(T){
    T delegate()pure _get;
    @property T ptr()const pure{ return _get(); }
    alias ptr this;
}

const(Unconstify!T) unconstify(T)(T ptr)pure{
    return Unconstify!T(()=>ptr);
}

The fix I originally proposed in the first post removes the unsoundness in the const system, but it is ugly. It means the line "const x = y;" fails if y is a delegate, but not if y is an instance of a struct wrapping a delegate. A more elegant solution would be to disallow calling const delegates whose context is not typed const or immutable. I.e. const(int delegate()const) can be called, but const(int delegate()) cannot be called.

Basically the same problem exists for immutable.

--
May 25, 2016
https://issues.dlang.org/show_bug.cgi?id=9149

--- Comment #12 from Steven Schveighoffer <schveiguy@yahoo.com> ---
Yes I see.

The issue is the conversion of the delegate type, when the context pointer is changed to const (but you didn't change the function pointer, so it still assumes it's argument is mutable).

I agree with you.

So basically, any struct or class instance cannot convert to const (or via pure constructor to immutable) if it contains a non-const delegate. Yuck, but I think we have to do that.

--
May 25, 2016
https://issues.dlang.org/show_bug.cgi?id=9149

--- Comment #13 from timon.gehr@gmx.ch ---
(In reply to Steven Schveighoffer from comment #12)
> Yes I see.
> 
> The issue is the conversion of the delegate type, when the context pointer is changed to const (but you didn't change the function pointer, so it still assumes it's argument is mutable).
> 
> I agree with you.
> 
> So basically, any struct or class instance cannot convert to const (or via pure constructor to immutable)

Do you have an example where conversion to immutable for a strongly pure constructor leads to problems?

> if it contains a non-const delegate. Yuck,
> but I think we have to do that.

We can't (for class references, you never know whether some subclass might have a mutable delegate field). We need to do something else, but all options I have proposed so far are quite ugly (or become ugly when considering all the details required to make them work), so I'm open to different proposals.

--
May 25, 2016
https://issues.dlang.org/show_bug.cgi?id=9149

--- Comment #14 from Steven Schveighoffer <schveiguy@yahoo.com> ---
(In reply to timon.gehr from comment #13)
> Do you have an example where conversion to immutable for a strongly pure constructor leads to problems?

Basically, the example in comment 3, but with the delegate not being const.

> We can't (for class references, you never know whether some subclass might have a mutable delegate field). We need to do something else, but all options I have proposed so far are quite ugly (or become ugly when considering all the details required to make them work), so I'm open to different proposals.

Oh crap. Yeah that's a huge problem. The only thing I can think of is to disallow const(A) if A has a non-const delegate. And disallow overriding any const base functions.

--
May 26, 2016
https://issues.dlang.org/show_bug.cgi?id=9149

--- Comment #15 from Sobirari Muhomori <dfj1esp02@sneakemail.com> ---
If we have syntax to declare delegates with function attributes and disambiguate context attributes, why not implement contravariance check? It's likely to be big and complex, but it's pure, doesn't change the compiler state, doesn't even allocate memory, only takes two const types and returns bool - unlikely to cause serious side effects.

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=9149

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P2                          |P3

--
February 02, 2023
https://issues.dlang.org/show_bug.cgi?id=9149

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |qs.il.paperinik@gmail.com

--
January 11
https://issues.dlang.org/show_bug.cgi?id=9149

timon.gehr@gmx.ch changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|Disallow converting         |Disallow calling const
                   |delegates to const          |delegates with a mutable
                   |                            |context

--
January 11
https://issues.dlang.org/show_bug.cgi?id=9149

--- Comment #16 from timon.gehr@gmx.ch ---
(In reply to timon.gehr from comment #11)
> 
> The fix I originally proposed in the first post removes the unsoundness in the const system, but it is ugly. It means the line "const x = y;" fails if y is a delegate, but not if y is an instance of a struct wrapping a delegate. A more elegant solution would be to disallow calling const delegates whose context is not typed const or immutable. I.e. const(int delegate()const) can be called, but const(int delegate()) cannot be called.
> 
> Basically the same problem exists for immutable.

I updated the title to reflect this more elegant solution.

--
January 13
https://issues.dlang.org/show_bug.cgi?id=9149

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |safe
                 CC|                            |bugzilla@digitalmars.com

--
1 2
Next ›   Last »