Worst ideas/features in programming languages?

deadalnix deadalnix at gmail.com
Fri Oct 15 23:58:34 UTC 2021

On Friday, 15 October 2021 at 21:55:55 UTC, SealabJaster wrote:
> On Friday, 15 October 2021 at 16:44:57 UTC, deadalnix wrote:
>> Then end result in practice is that almost everything uses the 
>> GC, and that @safe and @nogc are almost useless.
> Is there anything we can do to start addressing this, and the 
> other woes people have brought up?
> The answer is likely no, so I foresee these same things popping 
> up over and over and over again with no resolution since we 
> seem to have dug ourselves into a corner.

Well at some point we need to make choices about the invariant we 
want and stick with them.

Considering D's values, I'd say the solution that make sense is 
to allocate using the GC, have an ownership system on top of it 
that can free most things safely. You'll note that is is possible 
to build a GC that is as fast as malloc free (for instance, I was 
able to build a GC on top of jemalloc, and the only thing I had 
to add is one hashmap store when allocating chunk of size bigger 
than 4MB. this happens almost never and when it does, memory 
allocation is usually not the problem as simply filling these 4MB 
with literally anything is far more work than the work the 
allocator does (to be 100% fair, this doesn't work with all 
mallocs, a tcmalloc style structure wouldn't cut it for instance, 
but jemalloc is notorious to be one of the fastest and bestest so 
we are not making a big concession).

So using a GC instead of malloc/free is very much viable. In 
fact, because we know if something is shared or not, I bet we can 
do something that is even faster than traditional mallocs.

So we allocate on the GC, always and use ownership on top of it. 
Ownership should allow you to express common 
allocation/disposition patterns, and when you can't, either you 
leak to the GC, or you free explicitly, which is unsafe.

That require repurposing @nogc as preventing leaking from the 
ownership system to the GC rather than allocating on the GC - 
which in itself is no problem if the allocations are freed 

There are a ton of added benefit that come attached to this if 
done properly, like solving a ton of problems with shared.

Even tricky situations such as @nogc exception become trivial in 
that model. Consider:

void foo() {
     // Allocate the exception using the GC. The exception is
     // an owned(Exception), and the corresponding overload from
     // the runtime is called.
     // Ownership of the exception is transferred to the runtime.
     // The ownership system didn't lose track of the exception, so
     // foo can be @nogc .
     throw new Exception();

void bar() {
     try {
     } catch(Exception e) {
         // The ownership of the Exception is transferred back to 
         // user's code. The Exception doesn't leave the catch 
         // so it can be freed automatically without the user 
having to
         // do anything.
         // In practice, that require the runtime to provide the
         // exception handler with knowledge of the exception being
         // owned or not and a runtime check, so that, if it is 
         // it is freed.
         // bar can also be @nogc , because either the exception 
is owned
         // in which case it is freed and no leak occurred, or the 
         // is not owned, in which case the leak happened 
somewhere else.
         // In that case, this somewhere else cannot be @nogc .

You'll note that the ownership system does not need to be as rich 
as Rust's, because there is always the option to fallback on the 
GC or on unsafe constructs.

More information about the Digitalmars-d mailing list