November 14, 2021

On Sunday, 14 November 2021 at 07:16:43 UTC, Walter Bright wrote:

>

On 11/12/2021 4:31 AM, Steven Schveighoffer wrote:

>

One of the prerequisites to doing reference counting is to have a mutable piece of data inside an immutable piece of data.

Or maybe just give up on having immutable ref counted objects. Ref counted objects are mutable.

The object can still be immutable, but the reference count and the references, save for weak pointers, can't. I think.

November 14, 2021
On Sunday, 14 November 2021 at 09:28:14 UTC, Ola Fosheim Grøstad wrote:
> On Sunday, 14 November 2021 at 09:19:24 UTC, Elronnd wrote:
>> I don't think this makes pure functions less interesting or meaningful from a practical standpoint.
>
> Just remove the claim that D privides strong purity... Leave it at weakly pure and list known caveats.

Yes!  It is already not strongly pure because it can mutate through its parameters.
November 14, 2021
On Sunday, 14 November 2021 at 07:16:43 UTC, Walter Bright wrote:
> On 11/12/2021 4:31 AM, Steven Schveighoffer wrote:
>> One of the prerequisites to doing reference counting is to have a mutable piece of data inside an immutable piece of data.
>
> Or maybe just give up on having immutable ref counted objects. Ref counted objects are mutable.

Yes That.
November 14, 2021

On Saturday, 13 November 2021 at 23:08:01 UTC, Stanislav Blinov wrote:

>

On Saturday, 13 November 2021 at 21:55:21 UTC, Steven Schveighoffer wrote:

>

You are not getting that the GC collecting has nothing to do with the pure function's executation. The GC hijacks the current thread to do its business, and then passes back control to the caller.

...while introducing side effects, which the caller of the pure function was promised WOULD NOT HAPPEN, by the interface of the pure function.

Dude, I don't want to be rude, but you clearly don't have the prerequisite t add value to this thread. It's tiring to have to swift through pages of this to get to interesting infos.

Arguably, there may be a problem with the way finalizer are handled, but this has zero to do with the topic of this thread. You could remove the second function call that you assert could still fail. It has noting to do with the call, or it being pure of any of what you think it has to do with.

Please do not clutter this thread.

November 14, 2021
On Sunday, 14 November 2021 at 07:16:43 UTC, Walter Bright wrote:
> On 11/12/2021 4:31 AM, Steven Schveighoffer wrote:
>> One of the prerequisites to doing reference counting is to have a mutable piece of data inside an immutable piece of data.
>
> Or maybe just give up on having immutable ref counted objects. Ref counted objects are mutable.

That's best option imho. The ref counted objects should be mutable, while the payload, being of any constness level.

Like why do we even try to have ref counters be immutable? By their nature, they imply that some data is going to be modified (counter).
We could simply disable the ability to construct const and immutable versions of them, and that would remove the problem entirely.

For the case when a mutable ref counter becomes const, we could just disable access to the payload, forcing user to fix their code.
Or the counter could return a wrapper over payload that is not copyable or assignable, forcing user, to use wrapper with payload as soon as it was returned. Wrapper would have then an opDispatch overload, in order to not expose the payload to the user, and hence allow borrowing.

Best regards,
Alexandru.

November 14, 2021
On 14.11.21 08:16, Walter Bright wrote:
> On 11/12/2021 4:31 AM, Steven Schveighoffer wrote:
>> One of the prerequisites to doing reference counting is to have a mutable piece of data inside an immutable piece of data.
> 
> Or maybe just give up on having immutable ref counted objects. Ref counted objects are mutable.

Yes, this is definitely a reasonable way to resolve this debate.
November 14, 2021
On 11/14/2021 10:02 AM, Timon Gehr wrote:
> On 14.11.21 08:16, Walter Bright wrote:
>> On 11/12/2021 4:31 AM, Steven Schveighoffer wrote:
>>> One of the prerequisites to doing reference counting is to have a mutable piece of data inside an immutable piece of data.
>>
>> Or maybe just give up on having immutable ref counted objects. Ref counted objects are mutable.
> 
> Yes, this is definitely a reasonable way to resolve this debate.

Sometimes the obvious way is the best way!

Note that one still can have an immutable *payload* for a ref counted object.
November 14, 2021
On 14.11.21 09:12, Walter Bright wrote:
> On 11/13/2021 11:16 PM, Walter Bright wrote:
>> Or maybe just give up on having immutable ref counted objects. Ref counted objects are mutable.
> 
> Let me expand on that a bit.
> 
> This conversation reminds me of the old "logical const" debate, where people wanted to have constant objects that were not constant. That just would not work with the notion of transitive const.
> ...

The GC is able to deallocate `immutable` data. I don't think it's entirely unreasonable to give that capability to @system user code as well, but saying `immutable` means GC or infinite lifetime is of course possible.

> Having a __mutable field in an immutable hierarchy is the same abomination. Attempting it immediately starts causing the rest of the type axioms in D to come apart.

Well, the way I imagined it to work is:

- Carefully define what the axioms are in terms of allowed equivalence transformations of source code.
- @trusted code that mutates __mutable data has to be prepared for any of those equivalence transformations.
- __mutable functions are exempt of most or all of those equivalence transformations.

In principle, this could work. (But of course, it would make the axioms more complex and may prevent an expansion of rewrites that are based on the simpler meaning of attributes in the future.)

> As Steven pointed out, sharing stops working.
> ...

Yes, but implicit sharing has other drawbacks, e.g., it may prevent thread-local GC for thread-local immutable data such as strings.

> It's like defining pi to be 3.0, and a right angle to be 89 degrees. Your house will not fit together if the corners are 89 degrees.
> 
> How does C++ manage it? They don't have immutable types. Const is just a documentation attribute.
> 
> How do functional languages do it? Reference counted types are not part of the type system. They are behind the curtain, just like how the gc works in D is behind the curtain, and associative arrays(!).
> ...

__mutable variables and functions are an attempt to formalize being "behind the curtain", so that the runtime ceases to be language magic and @system user code can have well-defined access to the other side of the curtain. This allows the runtime to be implemented in terms of straight lowering to templates without special rules.

> D has these choices:
> 
> 1. ref counted objects are mutable
> ...

Works, but you may have to extend it to "anything that's not allocated with the GC is mutable". Deallocation eventually will change the memory you pass into it.

> 2. ref counted objects are outside of the type system
> ...

For this to work, there still needs to be a careful definition what @trusted functions are allowed to do with data of certain qualification. I think adding some type system support that is strictly @system, like __mutable variables and functions is better than having no language support at all, because otherwise, in order to support reference counting, you may end up penalizing code that does not actually use it.

> 3. break the type system
> 
> I find (3) to be a bit ironic after D has been lambasted for having inconsistent semantic rules.
> ...

Yes, I don't think adding UB to the standard library is an option.

> PS. I suspect that ref counted shared mutable objects are an indicator of insanity.

Possibly, though it's hard to know everyone's use cases in advance.
November 14, 2021
On 14.11.21 19:08, Walter Bright wrote:
> On 11/14/2021 10:02 AM, Timon Gehr wrote:
>> On 14.11.21 08:16, Walter Bright wrote:
>>> On 11/12/2021 4:31 AM, Steven Schveighoffer wrote:
>>>> One of the prerequisites to doing reference counting is to have a mutable piece of data inside an immutable piece of data.
>>>
>>> Or maybe just give up on having immutable ref counted objects. Ref counted objects are mutable.
>>
>> Yes, this is definitely a reasonable way to resolve this debate.
> 
> Sometimes the obvious way is the best way!
> 
> Note that one still can have an immutable *payload* for a ref counted object.

I am not sold on that yet. How do you manually deallocate an immutable payload?
November 14, 2021
On Sunday, 14 November 2021 at 18:08:29 UTC, Walter Bright wrote:
> Sometimes the obvious way is the best way!
>
> Note that one still can have an immutable *payload* for a ref counted object.

Maybe, it is reasonable, but I think we didn't fully explore mutable, we simply have to take a different route than C++ did. As I see it, the problem in D is forced transitivity.

immutable(mutable(int))  = immutable(int) (Unlike C++ !)
immutable(mutable(int)*) = immutable pointer to mutable int

Punching holes in immutable objects like C++ did causes major issues as the object might be stored in read-only memory or shared, etc.