If a const/immutable member function tries to modify the contents of its struct or class, the error message is present (ok) but confusing (not ok).
Example:
-----
struct S {
int v;
void fun () const {v++;}
void gun () immutable {v++;}
}
class C {
int v;
void fun () const {v++;}
void gun () immutable {v++;}
}
void main () {}
-----
Error message:
-----
const_member.d(3): Error: can only initialize const member v inside constructor
const_member.d(4): Error: can only initialize const member v inside constructor
const_member.d(8): Error: can only initialize const member v inside constructor
const_member.d(9): Error: can only initialize const member v inside constructor
-----
The error is indeed there: none of these functions are allowed to alter "v". However, the error message text is confusing.
First, member "v" is not constant - the method is. So, no apparent reason to mention the constructor.
Second, altering a variable is not necessarily initialization ("v++;").
Comment #1 by gassa — 2014-05-21T08:00:42Z
Created attachment 1357
source code of the demonstrating example
Comment #2 by andrej.mitrovich — 2014-05-21T08:29:57Z
(In reply to Ivan Kazmenko from comment #0)
> First, member "v" is not constant - the method is.
No, it's not the 'method', it's the 'this' reference which is constant. And const is transitive in D, which means all fields are constant. The above is equivalent to:
-----
struct S {
const(int) v; // as seen from 'fun'
void fun () const {v++;}
}
struct S {
immutable(int) v; // as seen from 'fun'
void fun () immutable {v++;}
}
-----
However I do agree the diagnostic could be improved a bit.
Comment #3 by bearophile_hugs — 2014-05-21T08:32:52Z
What error message do you suggest? Perhaps something like this?
test.d(3): Error: const methods (like 'S.fun') cannot modify instance members (like 'S.v'), only constructors can initialize them
test.d(4): Error: immutable methods (like 'S.gun') cannot modify instance members (like 'S.v'), only constructors can initialize them
Comment #4 by gassa — 2014-05-21T10:28:35Z
(In reply to bearophile_hugs from comment #3)
> What error message do you suggest? Perhaps something like this?
>
> test.d(3): Error: const methods (like 'S.fun') cannot modify instance
> members (like 'S.v'), only constructors can initialize them
> test.d(4): Error: immutable methods (like 'S.gun') cannot modify instance
> members (like 'S.v'), only constructors can initialize them
The part about constructors is formally false: not only constructors can initialize a non-const instance member.
Here's a C++ variant and the respective errors for inspiration:
-----
struct S {
int v;
void fun () const {v++;}
};
class C {
int v;
void fun () const {v++;}
};
int main (void) {}
-----
GCC - g++ errors:
-----
const_member.cpp: In member function 'void S::fun() const':
const_member.cpp:3:25: error: increment of member 'S::v' in read-only object
void fun () const {v++;} ^
const_member.cpp: In member function 'void C::fun() const':
const_member.cpp:7:25: error: increment of member 'C::v' in read-only object
void fun () const {v++;}
^
-----
CLang - clang++ errors:
-----
const_member.cpp:3:25: error: read-only variable is not assignable
void fun () const {v++;}
~^
const_member.cpp:7:25: error: read-only variable is not assignable
void fun () const {v++;}
~^
-----
Visual Studio 12 - cl.exe errors:
-----
const_member.cpp(3) : error C3490: 'v' cannot be modified because it is being accessed through a const object
const_member.cpp(7) : error C3490: 'v' cannot be modified because it is being accessed through a const object
-----
I'd say Visual Studio's message is the most readable.
Comment #5 by gassa — 2014-05-21T10:32:56Z
(In reply to Andrej Mitrovic from comment #2)
> (In reply to Ivan Kazmenko from comment #0)
> > First, member "v" is not constant - the method is.
>
> No, it's not the 'method', it's the 'this' reference which is constant. And
> const is transitive in D, which means all fields are constant. The above is
> equivalent to:
>
> -----
> struct S {
> const(int) v; // as seen from 'fun'
> void fun () const {v++;}
> }
>
> struct S {
> immutable(int) v; // as seen from 'fun'
> void fun () immutable {v++;}
> }
> -----
>
> However I do agree the diagnostic could be improved a bit.
Thank you for the explanation! I see now how it makes sense from the compiler's point of view. For the programmer however, it is convenient (and "safe", right?) to reason as "method is constant means it can not modify its object", and reading the current message somewhat breaks that model of thinking.