Thread overview
Second Draft: Placement New Expression
3 days ago
Walter Bright
2 days ago
Paul Backus
2 days ago
Paul Backus
2 days ago
Paul Backus
2 days ago
Walter Bright
2 days ago
Paul Backus
3 days ago
https://github.com/WalterBright/documents/blob/37206e8aad453aa115329f4465fc5b83bca4ff66/placementnew.md

as the first draft did not survive the implementation:

https://github.com/dlang/dmd/pull/17057
2 days ago
This still includes typed expressions, which I have some concerns about.

We should not be condoning uninitialized memory as having a type. It can only cause problems for people. If we stick to ``void[]`` as the input, we can limit the source to ``@system`` code only.

No double-init bugs please.

The side benefit of this, is the the length is known. If not big enough, return null.

At the very least we should think about how to make a memory safety DFA with one layer of indirection support, so not just the variable being known to be initialized, but what the pointer points to also being initialized. That would make this a whole lot safer.

> If one desires to use classes without the GC, such as in BetterC, it's just awkward to use emplace.

Not true, emplace is the easiest part of it as it becomes library code.

No reference counting on classes, lack of ability to mix -betterC with full D.

https://github.com/ldc-developers/ldc/issues/4779

These are the problems that need solving.

This is how I solved RC classes in -betterC, note that everything is templated (sigh), and that I have down casting working.

https://github.com/Project-Sidero/basic_memory/blob/main/source/sidero/base/allocators/classes.d#L183

> The use of placement new is not allowed in @safe code.

Excellant!

Although I would prefer us to disallow casting to ``void*`` and ``void[]`` also in ``@safe``.

Still too easy to introduce memory unsafe behaviors.

> To allocate storage with an allocator function such as malloc(), a simple template can be used:

Why not support calling the allocator with the size needed?

```d
struct Allocator {
	void[] allocate(size_t);
}

Allocator a;

new (allocator) S;
new (malloc) S;
```

DONE.
2 days ago
On 19/11/2024 6:05 PM, Richard (Rikki) Andrew Cattermole wrote:
>  > To allocate storage with an allocator function such as malloc(), a simple template can be used:
> 
> Why not support calling the allocator with the size needed?
> 
> ```d
> struct Allocator {
>      void[] allocate(size_t);
> }
> 
> Allocator a;
> 
> new (allocator) S;
> new (malloc) S;
> ```
> 
> DONE.

There are three reasons that motivate me for allocator support:

1. It would be @safe.
2. There is no trait like ``__traits(allocateSize, T)``/``__traits(allocateSize, T, arrayCount)``. Handle overflow correctly and "just work" regardless of type, i.e. class vs struct vs array has a very different way of getting allocation size.
3. Needing wrapper functions for this is genuinely silly. As a result I don't understand why it hasn't been adopted already.

2 days ago
On Tuesday, 19 November 2024 at 05:05:57 UTC, Richard (Rikki) Andrew Cattermole wrote:
> This still includes typed expressions, which I have some concerns about.
>
> We should not be condoning uninitialized memory as having a type. It can only cause problems for people. If we stick to ``void[]`` as the input, we can limit the source to ``@system`` code only.
>
> No double-init bugs please.

+1

Using a typed lvalue instead of void[] is just asking to shoot yourself in the foot, especially when it comes to const/immutable:

    struct S { int i; char c; }

    void main()
    {
        S dest;
        immutable(S)* p = new immutable(S)(dest)(123, 'A');
        assert(p.i == 123 && p.c == 'A');
        dest.i = 0; // oops, undefined behavior!
    }
2 days ago
On Tuesday, 19 November 2024 at 05:17:20 UTC, Richard (Rikki) Andrew Cattermole wrote:
> On 19/11/2024 6:05 PM, Richard (Rikki) Andrew Cattermole wrote:
>> Why not support calling the allocator with the size needed?
>> 
>> ```d
>> struct Allocator {
>>      void[] allocate(size_t);
>> }
>> 
>> Allocator a;
>> 
>> new (allocator) S;
>> new (malloc) S;
>> ```
>> 
>> DONE.
>
> There are three reasons that motivate me for allocator support:
>
> 1. It would be @safe.

It would not be @safe, because there is no way the compiler can be sure that the void[] returned from allocate will not be aliased by other pointers/references/slices. The programmer would have to verify that for each individual allocator implementation, and use @trusted once they had done so.
2 days ago
On 20/11/2024 8:08 AM, Paul Backus wrote:
> On Tuesday, 19 November 2024 at 05:17:20 UTC, Richard (Rikki) Andrew Cattermole wrote:
>> On 19/11/2024 6:05 PM, Richard (Rikki) Andrew Cattermole wrote:
>>> Why not support calling the allocator with the size needed?
>>>
>>> ```d
>>> struct Allocator {
>>>      void[] allocate(size_t);
>>> }
>>>
>>> Allocator a;
>>>
>>> new (allocator) S;
>>> new (malloc) S;
>>> ```
>>>
>>> DONE.
>>
>> There are three reasons that motivate me for allocator support:
>>
>> 1. It would be @safe.
> 
> It would not be @safe, because there is no way the compiler can be sure that the void[] returned from allocate will not be aliased by other pointers/references/slices. The programmer would have to verify that for each individual allocator implementation, and use @trusted once they had done so.

If there is anything like that is occurring outside of an allocator, or a misbehaving allocator, what expression you used to call an allocator is irrelevant, you have significantly bigger problems to attend to.

At the very least you will have program corruption, at best a crash.

I've experienced and debugged this plenty, without the need for placement new.

2 days ago
On Tuesday, 19 November 2024 at 21:18:53 UTC, Richard (Rikki) Andrew Cattermole wrote:
> On 20/11/2024 8:08 AM, Paul Backus wrote:
>> It would not be @safe, because there is no way the compiler can be sure that the void[] returned from allocate will not be aliased by other pointers/references/slices. The programmer would have to verify that for each individual allocator implementation, and use @trusted once they had done so.
>
> If there is anything like that is occurring outside of an allocator, or a misbehaving allocator, what expression you used to call an allocator is irrelevant, you have significantly bigger problems to attend to.
>
> At the very least you will have program corruption, at best a crash.

I agree. If someone makes a mistake here, it could lead to program corruption. That's exactly why it can't be @safe.
2 days ago
On 11/19/2024 11:02 AM, Paul Backus wrote:
> Using a typed lvalue instead of void[] is just asking to shoot yourself in the foot, especially when it comes to const/immutable:

This (and some other reasons) is why placement new will not be allowed in @safe code. The compiler will never be able to properly vet the provenance of the memory being overwritten by placement new.
2 days ago
On Wednesday, 20 November 2024 at 01:49:23 UTC, Walter Bright wrote:
> On 11/19/2024 11:02 AM, Paul Backus wrote:
>> Using a typed lvalue instead of void[] is just asking to shoot yourself in the foot, especially when it comes to const/immutable:
>
> This (and some other reasons) is why placement new will not be allowed in @safe code. The compiler will never be able to properly vet the provenance of the memory being overwritten by placement new.

I agree that it can't be @safe, void[] or not. But my impression is that even in @system code, D generally tries to guide the programmer away from error-prone constructs (for example, requiring an explicit `= void` to leave a variable uninitialized). Using a void[] instead of a typed lvalue would be consistent with that approach.