November 10, 2021

On Wednesday, 10 November 2021 at 18:50:26 UTC, Paolo Invernizzi wrote:

>

On Wednesday, 10 November 2021 at 17:24:03 UTC, deadalnix wrote:

>

On Wednesday, 10 November 2021 at 17:09:05 UTC, H. S. Teoh wrote:

>

Isn't that what @disable this() is for?

And to be pedantic, the object was constructed -- by the default ctor. If you didn't want that, you should @disable this().

T

No.

Everything that is destructed must have been constructed. It is the only way you can enforce invariant within a type.

Invariants must hold also with structures initialised from '.init', if you don't want to @disable this()...

The semantics of struct .init initialization are (nearly) equivalent to mandating that this() be pure, allocate no memory, and work in CTFE. This does significantly limit what invariants can be established.

November 10, 2021

On Tuesday, 9 November 2021 at 17:04:29 UTC, Paul Backus wrote:

>

On Tuesday, 9 November 2021 at 06:32:40 UTC, tsbockman wrote:

>

On Tuesday, 9 November 2021 at 03:43:01 UTC, Paul Backus wrote:
How? All of the runtime borrow checking schemes that I have considered turn out to have the same fundamental problems as reference counting, when examined closely.

Here's a basic sketch of the scheme I had in mind: https://gist.github.com/run-dlang/d1982a29423b2cb545bc9fa452d94c5e

Thanks.

>

It's entirely possible I've overlooked something and this is actually unsound. As Andrei says: "destroy!"

The general idea is possibly sound, although the current implementation definitely is not.

If your runtime borrow checks were combined with the language enhancements that I suggested in our previous discussion, I think it might actually be possible to write a nice @safe reference counting API that supports @safe reassignment/reallocation/resizing.

https://forum.dlang.org/post/zsjqqeftthxtfkytrnwp@forum.dlang.org
https://issues.dlang.org/show_bug.cgi?id=21981

November 10, 2021

On Wednesday, 10 November 2021 at 13:52:26 UTC, deadalnix wrote:

>

On Tuesday, 9 November 2021 at 18:33:01 UTC, Atila Neves wrote:

>

I think that C++'s greatest gift to the world was the destructor. We have those too! Let's use them.

Indeed, but I have unfortunate news. We broke the gift. In D, object can be destroyed without being constructed first.

Consider: https://godbolt.org/z/EdW75jWGn

This is the first problem we need to fix here, if we don't want to have to plaster our code with runtime checks.

How is that a problem, or, more to the point, how is D breaking anything here, as compared to C++? The latter effectively works by convention with its "valid, but unspecified state" for stdlib moved-from objects, and it's the best it can afford. We won't have that. The state is specified - it's .init. Right now it's also a mere convention, but it is effectively going to be set in stone with the move semantics DIP. It's a huge win as it allows the language to mandate rules for destructor elision, which C++ can't and won't do. I'd go so far as to argue that in a future version of D, the code presented above won't be calling a destructor at all.

November 10, 2021

On Wednesday, 10 November 2021 at 20:35:57 UTC, Stanislav Blinov wrote:

>

It's a huge win as it allows the language to mandate rules for destructor elision, which C++ can't and won't do.

How come? In order to know that something has been moved, you would also know the state of the object, so I don't see how D get any advantage over C++ here. Unless you in the type system distinguish between active and inactive objects.

November 11, 2021

On Wednesday, 10 November 2021 at 20:35:57 UTC, Stanislav Blinov wrote:

>

How is that a problem, or, more to the point, how is D breaking anything here, as compared to C++?

It break the construction/destruction invariant.

>

The latter effectively works by convention with its "valid, but unspecified state" for stdlib moved-from objects, and it's the best it can afford. We won't have that. The state is specified - it's .init. Right now it's also a mere convention, but it is effectively going to be set in stone with the move semantics DIP. It's a huge win as it allows the language to mandate rules for destructor elision, which C++ can't and won't do. I'd go so far as to argue that in a future version of D, the code presented above won't be calling a destructor at all.

copy and destruction elision does not require to break the ctor/dtor invariant. I would know, the proposal that is now on the table is a variation of a proposal I made almost 10 years ago. And the move semantic part of it is broken.

November 11, 2021

On Thursday, 11 November 2021 at 00:35:56 UTC, deadalnix wrote:

>

copy and destruction elision does not require to break the ctor/dtor invariant. I would know, the proposal that is now on the table is a variation of a proposal I made almost 10 years ago. And the move semantic part of it is broken.

If it requires a move to set it to .init then it is at least highly inefficient. Just think about instances that are 64KiB in size (like buffer nodes).

November 11, 2021

On Tuesday, 9 November 2021 at 19:39:15 UTC, Stanislav Blinov wrote:

>

On Tuesday, 9 November 2021 at 18:33:01 UTC, Atila Neves wrote:

>

On Tuesday, 9 November 2021 at 17:26:32 UTC, Stanislav Blinov wrote:

>

On Tuesday, 9 November 2021 at 17:15:59 UTC, Atila Neves wrote:

Could you please explain why you'd rather do that instead of using the equivalent of C++'s std::{vector, unique_ptr, shared_ptr} and Rust's std::{vector, unique_ptr, shared_ptr}? I cannot myself imagine why anyone would want to.

Instead? Not instead. Together with. It's all well and fine to rely on proven library solutions. But I'd rather a D or C++ programmer, when faced with necessity,

I have not yet encountered cases where it would be necessary that aren't "I'm implementing the standard library".

>

be able to write their allocations correctly, and not hide under a rug because Herb'n'Scott tell 'em that's "bad practice".

I think that decades of experience (and tools like valgrind and asan) have shown that programmers aren't able to write their allocations correctly.

>

We already have at least two (three?) generations of programmers who literally have no clue where memory comes from. If we keep this up, in a couple decades "nobody" (your definition of nobody) would be able to write you a better malloc for your next generation of platforms and hardware.

I don't think this is a problem.

>

Take a peek in the learn section. Person asks how to translate a simple C program into D. Buncha answers that all amount to "allocate craptons of memory for no reason". At least one from a very well known D educator. Only no one even mentions any allocations at all. Why even talk about it, right?

I wouldn't care about it either.

> >

My advice is that unless you have a very good reason not to, just use the GC and call it a day.

Who, using a SYSTEMS language, should not have a reason to care about their memory?

Me, ~99.9% of the time.

My algorithm:

  1. Write code
  2. Did I notice it being slow or too big? Go to 4.
  3. Move on to the next task
  4. Profile and optimise, go to 2.

I definitely don't miss having to make things fit into 48k of RAM. I wrote code for a microcontroller once with 1k with addressable bits. Good times. Sorta.

November 11, 2021

On Wednesday, 10 November 2021 at 13:52:26 UTC, deadalnix wrote:

>

On Tuesday, 9 November 2021 at 18:33:01 UTC, Atila Neves wrote:

>

I think that C++'s greatest gift to the world was the destructor. We have those too! Let's use them.

Indeed, but I have unfortunate news. We broke the gift. In D, object can be destroyed without being constructed first.

Consider: https://godbolt.org/z/EdW75jWGn

This is the first problem we need to fix here, if we don't want to have to plaster our code with runtime checks.

@disable this();, but you knew that. It's true that requiring a programmer to do something to prevent bugs is a terrible idea. Sigh.

November 11, 2021

On Thursday, 11 November 2021 at 09:15:54 UTC, Atila Neves wrote:

>

I have not yet encountered cases where it would be necessary that aren't "I'm implementing the standard library".

Not so sure about that. Arena allocators would be done with malloc, but you probably should wrap it with RAII.

Allocating directly from the OS (bypassing malloc) can in some cases be advantageous. But again, you are usually better off creating a RAII wrapper for it.

You also have dynamic stack allocation which can boost performance significantly. Sadly, Walter is against having this as a feature.

>

I definitely don't miss having to make things fit into 48k of RAM. I wrote code for a microcontroller once with 1k with addressable bits. Good times. Sorta.

That's a lot! As a teen I did a project on Motorola 6800. I think it was launched with a whopping 128 bytes of static RAM, so you had to make almost everything immutable (EPROM) and avoid deep call-trees.

November 11, 2021

On Thursday, 11 November 2021 at 09:24:17 UTC, Atila Neves wrote:

>

On Wednesday, 10 November 2021 at 13:52:26 UTC, deadalnix wrote:

>

On Tuesday, 9 November 2021 at 18:33:01 UTC, Atila Neves wrote:

>

I think that C++'s greatest gift to the world was the destructor. We have those too! Let's use them.

Indeed, but I have unfortunate news. We broke the gift. In D, object can be destroyed without being constructed first.

Consider: https://godbolt.org/z/EdW75jWGn

This is the first problem we need to fix here, if we don't want to have to plaster our code with runtime checks.

@disable this();, but you knew that. It's true that requiring a programmer to do something to prevent bugs is a terrible idea. Sigh.

@disable this just make the exemple slightly more convoluted, but the fundamental problem doesn't change.