On Monday, 2 April 2018 at 00:44:14 UTC, Jonathan M Davis wrote:
On Monday, April 02, 2018 00:25:52 Nicholas Wilson via
Digitalmars-d wrote:
On Sunday, 1 April 2018 at 17:08:37 UTC, Andrei Alexandrescu
wrote:
> On 4/1/18 10:59 AM, Nicholas Wilson wrote:
> [...]
> int[] sneaky;
> struct A
> {
>
> private int[] innocent;
> this(this)
> {
>
> sneaky = innocent;
>
> }
>
> }
> void main()
> {
>
> immutable a = A([1, 2, 3]);
> auto b = a;
> sneaky[1] = 42; // oops
> import std.stdio;
> writeln(a.innocent); // ooooops
>
> }
>
> Sadly this (and many similar ones) compiles and runs
> warning-free on today's compiler. We really need to close
> this loop, like, five years ago.
How much of this class of bug would be eliminated by requiring
that `this(this)` be pure for assignment to const and
immutable objects? Arguably this(this) should always be pure
in any sane program. The only reason I can think of is if
you're trying to perf the number of copies you're making, but
there is compiler help for that.
All kinds of things could be done with a postlbit costructor
that don't actually involve copying. These include logging or
printing something, and they could include stuff like reference
counting, which may or may not need access to something
external. debug statements would solve some uses cases but not
all. Requiring that this(this) be pure has some of the same
issues that requiring opEquals to be pure or const or whatever
has. It makes sense in _most_ cases, but occasionally, there
are good reasons for it not to be - especially in a systems
language.
I wasn't suggesting this a global requirement of all this(this)s,
only to the _postblit assignment to const and immutable objects_
( where
being pure would to disallow the above bug). Note that this should
still be able to be worked around by cast()s (which are un@safe)
and therefore require
@trusted to work in @safe code, in which case the programmer has
presumably
thought about the situation and knows what he's doing.