casting away const and then mutating

Steven Schveighoffer via Digitalmars-d digitalmars-d at puremagic.com
Thu Jul 23 13:20:04 PDT 2015


On 7/23/15 2:43 PM, anonymous wrote:
> Steven disagrees and thinks that there are cases where it's ok. Namely,
> this simple case would be ok:
>
> ----
> int x;
> const int *y = &x;
> *(cast(int *)y) = 5;
> ----

Yes, IMO, this should simply work and be consistent. The compiler could 
use willful ignorance to assume x is still 0, but I find that to be 
counterproductive. It would have to implement flow analysis to determine 
that y must point at x, and then simply ignore the assignment during 
that analysis.

I'll note that the reason I want to allow this, is because we have a 
case where the same implementation must be used for the const and 
mutable version of the function, but the return value is a template that 
varies on constancy. Therefore, you necessarily need 2 function 
definitions -- the compiler isn't smart enough (or maybe it's too 
smart?) to use inout(T) as a template parameter to the Range struct, and 
auto convert that back on return.

The nice thing about inout, is the compiler guarantees one 
implementation of the function, and the implementation will guarantee 
const is preserved. But on returning, the function puts the data back to 
the way it was. That's exactly what we want.

In this case, we can't use inout. So we have to cast (or alternatively, 
copy-paste implementation) one result to the other.

My opinion is, we should execute the implementation as if the object 
were const, and then cast back to mutable if we are using the mutable 
entry point. This allows the compiler to check the function 
implementation for const-correctness, vs. the other suggestion: casting 
the const object to a mutable one and then hoping the mutable function 
implementation is const-correct without compiler help.

The proposed usage of casting also does not mutate the data in the 
function that casts. It receives in a mutable object, and it outputs a 
reference to the mutable object. The compiler would have to go through 
great lengths to see that the source of the mutable range it's receiving 
comes from a const range, and then ignore the type system in order to 
elide a reloading of something that is miniscule compared to the 
function call itself.

>
> As I understand him, he's arguing that since the data is mutable, and
> since no function boundaries are crossed, compilers should not be
> allowed to do anything but the obvious with that code.
>
> I think we've exchanged all arguments we have, yet no one has been
> convinced by the other side.
>
> We've found the language spec to be a bit sparse on this. All I could
> find is essentially "you can't mutate through a const reference" [1],
> but no mention of if/when it's ok to cast a const reference to a mutable
> one (and then mutate).

Note that it does specifically mention immutable cannot be cast away and 
then modified (on that same page, see "Removing Immutable With A Cast"). 
It does not mention const, I assume that is on purpose.

-Steve


More information about the Digitalmars-d mailing list