Deprecating this(this)
Steven Schveighoffer
schveiguy at yahoo.com
Wed Apr 4 10:37:57 UTC 2018
On 4/3/18 5:44 PM, ag0aep6g wrote:
> On 04/03/2018 10:51 PM, Steven Schveighoffer wrote:
>> On 4/3/18 4:26 PM, ag0aep6g wrote:
> [...]
>>> If there's a problem with running two postblits on the same field,
>>> then I think constructors probably have similar issue. I'm having a
>>> hard time finding a good example, though. One where we could break
>>> immutable in an obvious way or some such.
>>
>> You may NOT want to run a postblit on the member. If all you are going
>> to do, for example, is reassign a variable, then running the postblit,
>> and then the destructor, just so you can overwrite it is pointless.
>
> Same with class constructors: You may not want to run `super` when
> you're just going to overwrite what it did. But the language doesn't
> give you a choice. It'll be called one way or another.
At least you can invoke the one you want, with postblit there is only
one "choice".
But this is a red herring -- we already have struct constructors, and
that requirement of invoking constructors on members is not present.
With structs, we have the possibility of initialization via different
mechanisms: constructor, postblit, .init. All of these are supported by
the struct member, but currently you can only invoke postblit if you are
in a postblit. And only at the beginning. I would like to see more
flexibility for copying.
> I'm not saying that imitating how constructors work will make the best
> possible copying mechanism. Something else might be superior in every
> way. It's just that so far the arguments against a constructor-like
> postblit also seem to apply to constructors as they are implemented.
For structs, using .init is a valid initialization, so it's completely
different from classes, where a constructor MUST be invoked. Indeed,
there is no mechanism to require calling struct member constructors in
the owner's ctor.
Stop thinking class constructors, and think struct constructors instead.
>> But more importantly, if the postblit of the member does something
>> crazy like stores a reference to itself as an immutable elsewhere, and
>> then the compiler allows overwriting, we now have problems.
>
> I'd love to see an example of this in code. The best I can come up with
> would be something like this (doesn't compile):
>
> ----
> import std.stdio;
>
> immutable(int)* p;
>
> struct S
> {
> int x;
> this(this) immutable
> {
> x = 42; /* First write. */
> .p = &this.x;
> writeln(p, " ", *p); /* Prints some address and 42. */
> }
> }
>
> struct T
> {
> S s;
> this(this) immutable
> {
> s = S(13); /* Second write. Breaking immutable? */
Of course this doesn't compile, because s is considered immutable by
now. What I was saying is that we can't allow postblit to modify data
that has already been postblitted, because of the reason this example is
showing.
> writeln(p, " ", *p); /* Same address, but 13. */
> }
> }
>
> void main()
> {
> immutable T foo;
> immutable bar = foo;
> }
> ----
>
> But that's essentially the same as the class example I posted. `*p`
> would only change values during the postblit run. Just like a
> constructor chain can write to the same field multiple times.
I don't think you should be able to write to the same field multiple
times in an immutable/const constructor. If so, that's a bug.
> That's kinda iffy, but I can't find a way to demonstrate some real,
> obvious damage.
Any place where an immutable can be observed to change between two reads
is breaking immutable.
-Steve
More information about the Digitalmars-d
mailing list