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