Const correctness revisited (proposal)
Oliver Dathe
o.dathe at gmx.de
Mon Mar 24 17:15:22 PDT 2008
Walter Bright wrote:
> That would be of very limited utility because I could not pass a
> const(T)[] array to the function. It's weird to have a function that
> doesn't modify its parameters where one could not pass const data to.
Ok I'll try something...
Definition:
If f has a 'tail const paramater' t of type T, then f must be compilable
if it also is compilable for typeof(t)=const(T) on data operations.
Otherwise it is an error.
T[] f(T[] t const) {
T sum;
foreach (i, ti; t) { sum+=ti; } // ok
auto h = t.toHash(); // ok, invariant data operation
static assert (is(typeof(t)==T[])); // ok, no data operation
// t[2] = ...; // error
// t.length = 17; // error
return t;
}
...
char[] a, y;
const(char)[] b;
const(char[]) c;
...
// all following three calls will succeed
// note: for all three returntype==typeof(y)==char[] holds
y=f(a);
y=f(b);
y=f(c);
You can see: If f is compilable, then the call to f succeeds if
T_param_at_call is implicitly convertible to const(T_param_at_func).
So a call to a function char[] foo(char[] x const) {...} with a
const(char)[] parameter also succeeds.
Would this also imply the call is sound? Btw: How or where is sound in
this context defined?
In general: That we define types with const properties where it makes
sense is really fine, no doubt! However, the problem is if we want to
pass an immutable view of usual mutable data to a function, the real
"solution" is apparently not to just use some const(char)[] as input
type because
a.) the Ts behind input usually are not really const but we just want an
immutable view on them. By using const(char)[]
b.) we are forced to use an evil const-away cast when we want to mutate
the result afterwards. To some degree that is contradictory and
counterproductive (cast-away-const==cast-away-sound right?).
I simply aim to be able to prove:
STATE before = STATE(x); // x + anything reachable through x
y=foo(x);
static assert (STATE(x)==before); // must be provable at compile time
This currently can be ensured by x beeing const. That is the way D2
currently forces. But this constness must not necessarily be a natural
attribute of the data! In most scenarios we may simply want to ensure
foo() is not mutating x without artificially constifying the data. I
think that is the heart of the ever upcoming 'const debacle'.
Also imagine: You have a lot of D1 code with 'in T[]' parameters but
you'd like to use them with a lot of const(T)[] variables where it makes
sense. Note: This is the same scenario as you mentioned in your post
before. Currently that will fail for the same reason. Now, let us try to
let calls to D1 functions succeed that do not explicitly declare const
parameters or tail const parameters. In order use them with our const(T)
input variable we could either
a.) call foo(const input) as proposed in my original post (enforce
immutability of the function regarding the parameter) or
b.) since input is const anyways, parameter tail constancy may
automatically be forced.
If we do so, we would also have a huge gain of D1 code that is usable in
a D2 const styled world! Not at least the optimizer will appreciate this
but also having tail const parameters in declarations will be of
valueble information to the user/reader of the code/docs.
Another Question: The transitive behaviour of const will also hold for
the planned D tail const methods? This would have great impact on a D2
version of the following dirty C++ code:
#include<cassert>
class A {
char* p;
public:
A() : p(new char[50]) {}
~A() { delete[] p; }
// within tail const methods typeof(this) is (A const *)
// but typeof(this->ptr) remains char* in C++, (nontransitive)
char* getp() const { return p; }
void mutate() const { p[5]=42; }
};
int main() {
A a;
char* ptr = a.getp();
ptr[5] = 17;
a.mutate();
assert(ptr[5]==42);
return 0;
}
So in D2 within tail const methods typeof(this.p)==const(char*) and
typeof(this.p[0])==const(char) holds? Did I get this right? That'd be
consistent with the rest and pretty cool I think.
More information about the Digitalmars-d
mailing list