logical const without casts!

Christophe travert at phare.normalesup.org
Fri Sep 30 11:51:19 PDT 2011


"Steven Schveighoffer" , dans le message (digitalmars.D:145850), a
> As long as you assume the context pointer is part of the state of the  
> aggregate, then yes.  But I don't see it that way.  The context pointer is  
> part of the state of the delegate, and the delegate reference itself is  
> the same as a function pointer -- it's not affected by immutable or const.

That is actually where our opinions differ.
I wouldn't blame the langage for choosing you proposal rather than mine. 
I just personnaly think my proposal in more in the spirit of the 
langage, and offer more guarantees when dealing with immutables.

> This also doesn't work:
Indeed. The compiler should not allow the implicit conversion of 
globalFoo to immutable.

> class Foo
> {
>     this(ref int _i) { dg = () { return _i; } }
>     ref const(int) delegate() const dg;
>     ref const(int) i() const { return dg(); }
> }
> 
> int globalInt;
> 
> immutable Foo globalFoo = Foo(globalInt);
^ error: can't cast ref int _i to immutable ref int in immutable 
Foo.this()._delegate_1.

> void thread1()
> {
>     writeln(globalFoo.i);
> }
> 
> int globalBar()
> {
>     spawn(&thread1);
>     globalInt = 5; // does thread1 see this change or not?
> }

> It looks like any time you call a delegate member of an immutable object,  
> it could access a context pointer that is not implicitly shared.

Not if the compiler cares to check the delegate context is indeed 
immutable when the immutable delegate is created. It is not much more 
complicated than if Foo contained an explicit pointer to i instead of a 
delegate

> Not to mention, what the hell does a const function mean for a delegate  
> literal?  The context pointer is the context of the function, not an  
> object.  How does that even work?

Internally, it is a pointer to a structure containing the delegate 
context that is generated by the compiler. If the delegate is const, the 
pointer should be a const pointer. If the delegate is immutable, it 
should be an immutable pointer, and the compiler as to check there is no 
mutable version of that pointer before making an implicit cast.

> What is probably the "right" solution is to disallow implicit immutable  
> objects which have a delegate.  This means:
> 
> a) you cannot initialize a shared or immutable such object without a  
> cast.  This means the line immutable Foo globalFoo = new Foo(globalInt) is  
> an error without a cast.

Agreed, but with my proposal, you can have an immutable Foo, if the 
delegate context pointer can be cast to immutable.

> b) Any time you have a const object that contains a delegate, it can be  
> assumed that the object is not shared.

If the object is const, you have no guarantee that the objet is not 
shared, making an exception for object containing a delegate is quite 
wierd.

> And then we avoid dealing with the const delegate issue altogether.

Dealing with this issue could be very useful for multithreaded 
applications.

>> With my proposal, you can very easily keep an immutable reference in a
>> const delegate. The delegate will just not be callable if its
>> function pointer is not const with regard to the context pointer.
> 
> You can also very easily keep a mutable reference in a const delegate  
> inside an immutable object.  It's not mutable through the delegate, but  
> it's also not immutable.

No, the compiler should check the delegate context is immutable when 
making the cast to immutable.

I admit you have found a very interesting corner-case for my proposal 
that I had not thought of that case. Thank you for that. I think the 
proposal passed the test (until now).




More information about the Digitalmars-d mailing list