On Friday, 19 February 2016 at 12:03:01 UTC, Walter Bright wrote:
On 2/19/2016 3:21 AM, Jonathan M Davis wrote:
D is definitely in a better boat in that it's easier to find and catch problems with const, but it really doesn't do much more to actually guarantee that a const object isn't being violated. Programmers are free to do horrible things
and mark it as @trusted,

The point of @trusted is it can be grepped for, and undergo extra scrutiny. The idea is to minimize @trusted sections. With C++, it's the WHOLE PROGRAM that has to be scrutinized.

This is ORDERS OF MAGNITUDE different.

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. It can just guarantee that so long as @trusted code behaves itself. So, that's an enormous improvement, but it still means that it's possible for you to pass an object to a function that takes its argument by const and end up with that object being mutated by that function - and without you knowing about it unless you go digging through the code for @trusted violations.

But even if the compiler completely succeeded at guaranteeing that an object is not mutated via a const reference, there's the problem that because D's const is so restrictive, a lot of D code ends up not using it, which means that it gets _zero_ benefit from const, whereas in C++, it would have been const, and const would have caught some bugs even if it didn't provide strong guarantees. So, the code that could have used const in C++ but can't in D suffers because it doesn't even have partial protection by const. It's only the code that doesn't need something like the mutable keyword and which doesn't need to interact with code that needs something like the mutable keyword that can benefit from D's const. For instance, very little generic code in D is able to mark its parameters as const even if it doesn't mutate it, because there's a high chance that someone is going to want to be able to use that function with a type that won't work with const.

So, I think that even if D's const is far better than C++'s where it does work, we're actually worse off than C++ in a lot of code, because there are a lot of places in D where it doesn't work, and we can't use const, whereas the same code in C++ could have. So, we end up with no protection instead of partial protection, which is not an improvement. It's like we've come up with tank armor to protect people from bullets, and we won't let anyone wear bullet proof vests anymore, because they're not as good as tank armor, and so the folks who can't do their jobs behind tank armor are screwed when the bullets come.

I'm proposing that we have something like

@mutable struct S
{
     int i;
     @mutable int* refCount;
     ...
}

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;

and that if it didn't, it wouldn't be compatible with the full type definition. But maybe I'm missing something with opaque types, since I don't use them much, and I don't think that I've ever used them in D. But the whole idea of putting @mutable on the type definition itself instead of just on the member variable was that opaque types would have to have it too and that seeing the @mutable members would not be required to know that a type contained @mutable members.

- Jonathan M Davis

Reply via email to