May 29, 2022
On Sunday, 29 May 2022 at 22:18:01 UTC, Walter Bright wrote:
> On 5/29/2022 2:05 PM, Paul Backus wrote:
>> The entire problem is that we *cannot* mix and match @live code with @safe code.
>> 
>> Nobody who cares enough about memory safety to be interested in @live is going to want to give up @safe in order to use it.
>
> @live does not subtract any safety from @safe.

But it doesn't add any either. All of the mistakes @live prevents you from making are already prevented by @safe on its own. The only place you get any safety benefit from @live is in @system code.

To be more precise about it: we cannot mix "code that benefits from @live" with @safe code, because "code that benefits from @live" is a subset of "@system code."
May 30, 2022

On Sunday, 29 May 2022 at 23:14:32 UTC, Paul Backus wrote:

>

@live and @safe are two different attribute, which are no different from ordinary @attributes.
You can add @live if you want to use @safe. It doesn't matter.
It's not that terrible.

May 30, 2022

On Monday, 30 May 2022 at 01:30:30 UTC, zjh wrote:

>

You can add @live if you want to use @safe.

@attribute is originally used for restriction.

May 29, 2022
On 5/29/2022 4:14 PM, Paul Backus wrote:
>> @live does not subtract any safety from @safe.
> 
> But it doesn't add any either. All of the mistakes @live prevents you from making are already prevented by @safe on its own.

It prevents use-after-free, double-free, and leaks.

> The only place you get any safety benefit from @live is in @system code.
> 
> To be more precise about it: we cannot mix "code that benefits from @live" with @safe code, because "code that benefits from @live" is a subset of "@system code."

There's nothing preventing marking a function as @live @safe.
May 30, 2022
On Monday, 30 May 2022 at 01:56:09 UTC, Walter Bright wrote:
> On 5/29/2022 4:14 PM, Paul Backus wrote:
>>> @live does not subtract any safety from @safe.
>> 
>> But it doesn't add any either. All of the mistakes @live prevents you from making are already prevented by @safe on its own.
>
> It prevents use-after-free, double-free, and leaks.

@safe already prevents use-after-free and double-free on its own, because @safe code can't call free() in the first place. Leaks are already handled by the GC or by reference counting. None of this requires or benefits from @live.

In fact, @live is actually an active hindrance, because it will nag you to manually dispose of pointers to memory that's already going to be cleaned up automatically by the GC.

> There's nothing preventing marking a function as @live @safe.

There is no benefit to marking a function as @live @safe instead of just plain @safe.
May 30, 2022
On Sunday, 29 May 2022 at 16:26:03 UTC, Walter Bright wrote:
> On 5/29/2022 7:18 AM, Paul Backus wrote:
>> Unfortunately it is not possible to write @safe code that relies on @live for lifetime tracking, so its utility is extremely limited in practice.
>
> I don't know what you mean.
>
> Unless you're referring to containers. I'm not well acquainted with Rust, but I think you can't write many containers there without dipping into unsafe code.

Have you considered starting with some simple container implementations and seeing how your design allows them to be @live @safe? It would be good if the discussion had some central & complete* examples that people can pick over. I feel like all this discussion without concrete code that does real work might easily lead to collective blind spots. Of course one must make sure the theory makes sense to ensure generality, but concrete examples are excellent checks.

* i.e. would actually be useful. Even an example showing how to implement a @live @safe array type would be enlightening. The best would be "this complete, useful library type sucks in D, here's how it would be much better with @safe @live D".

Forgive me if these already exist somewhere.
May 30, 2022
On Monday, 30 May 2022 at 18:05:56 UTC, John Colvin wrote:
> Have you considered starting with some simple container implementations and seeing how your design allows them to be @live @safe? It would be good if the discussion had some central & complete* examples that people can pick over. I feel like all this discussion without concrete code that does real work might easily lead to collective blind spots. Of course one must make sure the theory makes sense to ensure generality, but concrete examples are excellent checks.
>
> * i.e. would actually be useful. Even an example showing how to implement a @live @safe array type would be enlightening. The best would be "this complete, useful library type sucks in D, here's how it would be much better with @safe @live D".
>
> Forgive me if these already exist somewhere.

I'm not sure a container exist, but there are various code samples in bug reports and in discussion in this forum. This debate has been going on for literally a decade, and I guess there are only so many time people will go through the effort of coming up with a realistic piece of code to make a point.

In any case, it seems to me that we are suffering from the exact opposite problems. As far as I can tell, D is rolling out solution to specific problems after solution to specific problems, which balloons the complexity while never getting at the root of the problem.

Consider that type qualifier, DIP1000, @live, @nogc, RCObject, and probably a few more, are all variations around the theme of ownership. But because we look at it from a specific angle, and attack that angle, we just accumulate partial, but incomplete solutions.

When looking at it this way, the #1 problem D faces becomes invisible. yes, DIP1000 is simpler than ownership. Yes, @nogc is also simpler than ownership. Maybe - not sure - @live is simpler than ownership. RCObject is also definitively simpler than ownership. Type qualifier are also simpler than ownership.

But you know what is not simpler than ownership? Type qualifers + DIP1000 + @nogc + @live + RCObject. And yet, the power you get from them is also significantly less than full blown ownership.

There is a case to be made that we do not want ownership in D, because it is too complex, because Rust captured that market, or whatever. But then we got to embrace the GC, optimize allocations via escape analysis, and so on (a study of optimizations done for Java or JS would be a good primer to know what the options are here). Or we decide that we do want it.

What doesn't make sense is pretend we don't want it, and implement broken version of it after broken version of it. This only becomes apparent when you stop looking at individual examples, step back, and look at the emerging patterns.
May 30, 2022
On Mon, May 30, 2022 at 08:26:46PM +0000, deadalnix via Digitalmars-d wrote: [...]
> In any case, it seems to me that we are suffering from the exact opposite problems. As far as I can tell, D is rolling out solution to specific problems after solution to specific problems, which balloons the complexity while never getting at the root of the problem.

Totally agree with this!


> Consider that type qualifier, DIP1000, @live, @nogc, RCObject, and probably a few more, are all variations around the theme of ownership. But because we look at it from a specific angle, and attack that angle, we just accumulate partial, but incomplete solutions.

Yep.  Lately I've been feeling like we're missing the forest for the trees.  We're tackling every individual tree with heroic effort, but we've lost sight of the forest and where we want to be heading. (Or maybe we just can't come to an agreement of where we want to be heading, so we decide to tackle the entire forest, one tree at a time.) We're just inventing one ingenious engineering solution after another to deal with the tree immediately in front of us, accumulating technical debt, yet we have no idea what the next tree behind this one will be, let alone the rest of the forest.  In the end, we accumulate lots of powerful tools for cutting down individual trees but none that can take us through the forest, because we don't even know which direction we're supposed to be heading. We're just hoping and wishing that after tackling N trees ahead of us we will somehow magically make it to the end -- but what that end is, we don't have a clue.


> When looking at it this way, the #1 problem D faces becomes invisible. yes, DIP1000 is simpler than ownership. Yes, @nogc is also simpler than ownership. Maybe - not sure - @live is simpler than ownership. RCObject is also definitively simpler than ownership. Type qualifier are also simpler than ownership.
> 
> But you know what is not simpler than ownership? Type qualifers + DIP1000 + @nogc + @live + RCObject. And yet, the power you get from them is also significantly less than full blown ownership.

Exactly. We tackle individual trees marvelously, each with its own specialized tool. But put all those tools together, and we still can't take on the forest.


> There is a case to be made that we do not want ownership in D, because it is too complex, because Rust captured that market, or whatever. But then we got to embrace the GC, optimize allocations via escape analysis, and so on (a study of optimizations done for Java or JS would be a good primer to know what the options are here). Or we decide that we do want it.

IOW, decide which edge of the forest we want to end up on in the first place, before we engage our engineering genius to tackle individual trees! :-D


> What doesn't make sense is pretend we don't want it, and implement broken version of it after broken version of it. This only becomes apparent when you stop looking at individual examples, step back, and look at the emerging patterns.

I wouldn't say it's broken, each tool we invent works marvelously well against the tree directly ahead of us.  The problem is that we don't know which trees we should be tackling, and which side of the forest we want to end up in at the end.  We heroically deal with the tree of type qualifiers, then discover standing behind it tree of escaping references 1-level deep. We fell that with great aplomb, then we discover facing us the tree of escaping reference 2-levels deep.  We deal with that with equal engineering genius, but behind it stands another tree, requiring yet another heroic engineering effort to deal with.  With every tree we accumulate more technical debt, but we haven't even figured out whether all of them combined will get us "there" -- because we haven't even figured out where "there" is. :-/


T

-- 
Why ask rhetorical questions? -- JC
May 31, 2022
On 29.05.22 22:05, Walter Bright wrote:
> I'm aware of this, and Timon has also brought it up.
> 
> It's this way to enable people to mix and match code, because I doubt many would even try it if it was "turtles all the way down".

Sure, but @live fails at doing that. @live is redefining the meaning of certain built-in types within annotated functions. You can't just mix and match, because the caller and callee may disagree about the meaning of the function's interface. Function calls across the boundary engage in unsafe type punning. It's like calling a function assuming a wrong ABI.

The way to enable people to mix and match code is to make ownership and borrowing semantics additional features for user defined types to optionally use. That's also what you want in the end, and it can actually help make @safe more powerful along the way.
May 31, 2022

On Monday, 30 May 2022 at 21:08:20 UTC, H. S. Teoh wrote:

>

IOW, decide which edge of the forest we want to end up on in the first place, before we engage our engineering genius to tackle individual trees! :-D

In the words of our Chinese people,that , have not open the big picture?
Indeed, we cannot indulge in details .
We need macro thinking!
For example, who are our target users? What are we after?
I think since we have more than four compilers , let's serve for compiler programmers .
This is a direction. We can try to explore here first, right? After all, D teams are professional in the compiler domain.