An Issue I Wish To Raise Awareness On

Atila Neves via Digitalmars-d digitalmars-d at puremagic.com
Tue Jul 25 03:30:38 PDT 2017


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


More information about the Digitalmars-d mailing list