How to break const

Artur Skawina art.08.09 at gmail.com
Wed Jun 20 11:02:30 PDT 2012


On 06/20/12 15:58, Christophe Travert wrote:
> Artur Skawina , dans le message (digitalmars.D:170305), a écrit :
>> On 06/20/12 09:31, Christophe Travert wrote:
>>> Artur Skawina , dans le message (digitalmars.D:170191), a écrit :
>>>>> The proper way to do this is not cast, it is to give the proper 
>>>>> constness for all types and methods :
>>>>>
>>>>>    struct S {
>>>>>       int i; this(int i) { this.i = i; }
>>>>>       T* p; 
>>>>>       void f(int i) const { this.i = i; /*p.i++;*/ }
>>>>> // the commented part is illegal because S.f is const
>>>
>>> I missed that. Then I disagree with your use of delegates. The solution 
>>> here is to make the free f function to take a non const T*, since the 
>>> function tries to modify variables from that T instance (via a 
>>> delegate).
>>
>> The issue is the delegate definition - what exactly is a delegate?
>> My first message in this thread started with this sentence:
>> "It's fine, if you view a delegate as opaque". Because if you do, then
>> accesses via a delegates context pointer are no different from using
>> an external reference. That message also contained a program to show
>> how trivial bypassing const is, at least for impure functions. So
>> banning "unsafe" delegates wouldn't really change the situation.
> 
> Having opaque delegate and no holes in the langage is a possibility, but 
> not without changing the langage spec.
> 
> With opaque delegates, you can't have a pure delegate, only pure 
> function pointers, because pure means you do not access external data, 
> and accessing data pointed by a the opaque frame pointer of the delegate 
> would be accessing external data.
> 
> You may then redefine pure for delegate as delegates having only 
> immutable external data (const is not enough).
> 
> I'm definitely not in favor of that solution.

I agree with all of the above, maybe except the last sentence.
The choice is between a) status quo, where the delegates are treated
similarly to impure free functions, and b) handled "correctly". 
With scheme "a" I would expect to encounter genuine bugs extremely rarely,
if ever; while if "b" would be enforced, the bugs directly or indirectly
caused by working around the limitations would be plenty...
Having a "cleaner" design, but one that results in more bugs is not really
an improvement. Maybe there is a middle ground.

Anyway, that problem is not likely to get fixed quickly. In the mean time,
there are serious compiler bugs related to the thread subject, which likely
could. For example:

   import std.stdio;

   struct S {
      int i; this(int i) { this.i = i; }
      auto mutable() pure { return &i; }
      void iAintAfraidOfNoConst() const pure { *(&mutable)()=-1813; }
   }
   
   void main() {
      auto s = new immutable(S)(42);
      writeln(*s);
      s.iAintAfraidOfNoConst();
      writeln(*s);
   }

The '&const(this).mutable' operation is clearly bogus and should not be
allowed. But the compiler happily creates a delegate from a method and
an incompatible instance reference, which in this case results in 'const'
being dropped.

(I have no DMD - can't test if the problem is still there, hence can't
file a bug report)

artur


More information about the Digitalmars-d mailing list