Head Const

Jonathan M Davis via Digitalmars-d digitalmars-d at puremagic.com
Sat Feb 20 00:47:12 PST 2016


On Friday, 19 February 2016 at 21:53:16 UTC, Walter Bright wrote:
> On 2/19/2016 4:38 AM, Jonathan M Davis wrote:
>> Yes, as long as you have the source code, finding @trusted 
>> violations is _way_
>> easier in D than it is in C++, but the fact that it's possible 
>> to cast away
>> const and mutate still means that the compiler can't actually 
>> guarantee that an
>> object is not mutated via a const reference to it.
>
> All languages that guarantee safety have this issue - Rust and 
> C# have 'unsafe' blocks, and Java has the JNI C interface. Even 
> Haskell has its Foreign Function Interface.
>
> The idea is to encapsulate such, which D does as well as any 
> other language. This is not a defect of D.

I don't think that we should change D in that regard. It _is_ a 
problem with having "unsafe" blocks, and that's life with a 
systems language. I was just trying to make the point that the 
result is that the compiler can't actually guarantee that const 
isn't mutated. It can just reduce how much code could violate 
that guarantee and guarantee that as long as the programmer did 
the right thing in the @trusted code (or there is no @trusted 
code), then the guarantee about const not mutating will hold. So, 
it's making guarantees but with caveats where the caveats are 
fairly easy to track down (at least as long as you have the 
source), whereas C++'s guarantees have barn-sized caveats that 
are  _not_ easy to track down.

>>> This does not work for opaque types.
>>
>> Why not? I would expect the opaque type to have to have it 
>> too, e.g.
>>
>>      @mutable struct S;
>
> That would mean you're proposing '@mutable const' as a type 
> constructor, which you'd earlier said otherwise.

Sorry about that. I think that I missed the "struct" in the 
declaration that you wrote earlier and misunderstood what you 
were talking about, but the idea is that @mutable would be part 
of the type such that you wouldn't be slapping @mutable on every 
declaration that uses the type - e.g.

auto foo(@mutable S bar) {...}

wouldn't make sense (which is what I mistakenly thought you were 
referring to). But both when you have the full definition and an 
opaque declaration for the type, the @mutable has to be there, 
e.g.

@mutable struct S
{
    ...
}

or

@mutable struct S;

Then the fact that S has @mutable members is part of the type 
regardless of whether you see the full definition or an opaque 
one, and the compiler can treat it appropriately (also, any 
programmer trying to verify whether a type has @mutable members 
or not can look at either the full definition or the opaque one 
and see it at a glance). AFAIK, the only place that it would end 
up being hidden would be references to base classes, since the 
derived class could be @mutable, but the base class wouldn't be 
(since it has no @mutable members). However, since the @mutable 
would be visible when the type is constructed (since it would be 
constructing the derived type), the compiler could see that it 
wouldn't be legitimate to construct it as immutable (unless we 
figured out how to make @mutable work with immutable, but that's 
a whole other layer of complication of questionable value), which 
might introduce problems with pure functions implicitly casting 
to immutable if we're not careful, but I think that that's 
resolvable. Certainly, it would be impossible to construct an 
@mutable type as immutable.

But ultimately, any code that does not use @mutable should be the 
same as it is now, with the full set of guarantees that it 
currently has. It's just the new code that uses @mutable that 
would have reduced guarantees (but would then still have the full 
guarantees for the non- at mutable members), and it would give us a 
backdoor that would not run afoul of immutable. It would solve 
the major use cases that are causing folks to cast away const and 
mutate, thinking that it was legit as long as the data wasn't 
actually immutable - including the cases that Andrei has had 
recently with allocators and reference counts. So, we essentially 
get a type safe logical const, though obviously, as with 
@trusted, it'll still be up to the programmer to not be stupid 
about what they mark as @mutable. But it'll also be easily 
greppable like @trusted is (and actually, as ugly as those @ 
symbols arguably are, they really do make grepping easier by 
significantly reducing the risk of false positives).

- Jonathan M Davis


More information about the Digitalmars-d mailing list