On Monday, 24 July 2017 at 20:30:25 UTC, Jonathan M Davis wrote:
On Monday, July 24, 2017 2:30:01 PM MDT Atila Neves via Digitalmars-d wrote:
>> This is fine. What dmd does now is strip shared off of the >> `this` pointer, not the member variables. There's only a >> problem if the sharedness of the member variable(s) depends >> on sharedness of the enclosing object.
>
> What happens with something like
>
> struct S
> {
>
>     Foo* _foo;
>
>     ~this() {...}
>
> }
>
> shared S s;
>
> Inside the destructor, is what _foo points to still treated > as
> shared: shared(Foo)*?

No. This is what I meant by the sharedness depening on the enclosing object. However, there's a workaround:

struct Foo { }


struct S {

     Foo* _foo;
     bool _isShared;

     this(this T, U)(U foo) if(is(T == shared) && is(U ==
shared(Foo)*) || !is(T == shared) && is(U == Foo*)) {
         static if(is(T == shared)) _isShared = true;
         _foo = foo;
     }

     ~this() {
         import std.stdio: writeln;
_isShared ? writeln("shared dtor") : writeln("non-shared
dtor");
     }
}

void main() {
     auto f = Foo();
     auto sf = shared Foo();
     auto s = S(&f);
     auto ss = shared S(&sf);
}


It's annoying to use that bool up memory-wise, but I assume it's not a big deal for most applications.

In any case, that example wouldn't have worked anyway before my change to dmd - even creating the S struct would've been a compiler error.

The problem with this is that this means that shared is not being properly enforced by the compiler. Your workaround is a way for the programmer to figure out if the object is shared and do something differently based on that, but for the compiler to do what it's supposed to be doing with shared (e.g. prevent non-atomic operations), any indirections in the member variables must continue to be typed as shared inside the destructor, and that's clearly not happening right now, which is a serious problem IMHO. The situation may be better thanks to your changes in that some stuff is now possible that should be possible and was not before, but it's not completely sound as far as the type system goes, and we really should be fixing it so that shared is properly enforced rather than just blindly stripped off.

- Jonathan M Davis

I agree that this could be a problem, and that the proper solution is probably to allow the user to define more than one destructor. The problem isn't just with shared - immutable is similar, since you'd be able to invoke undefined behaviour from the destructor since immutable would be cast away and the compiler wouldn't even warn you. And that was already the behaviour in dmd. I think the situation isn't ideal but better than before.

I also think that while the problem exists, I don't think it'll be common. This would only affect structs that can be shared _and_ non-shared (or immutable).

This will require a DIP, methinks.

Atila

Atila

Reply via email to