June 09, 2021
On 6/9/2021 10:54 AM, Timon Gehr wrote:
> AssertError is still *caught* /by the language/ on in contract inheritance.

That's a fault in the language design. I do make a mistake now and then :-/ All I can do is grovel and beg forgiveness.
June 09, 2021
On 6/8/2021 11:58 PM, Max Samukha wrote:
> Placing (part of) constructor logic into a separate function that may throw, and pretending that a partially constructed state is a valid state - why do you think it is better?

As I remarked, it makes the code easier to reason about.
June 09, 2021
On 6/9/2021 7:01 AM, Steven Schveighoffer wrote:
> I'm 99% sure we could have a nogc stack trace for InvalidMemoryOperationError if we had a nogc demangler. Everything else seems already nogc, just not fully marked.

I don't believe it would be hard to make a nogc demangler, even if it used malloc.

Even better, provide a "sink" parameter for the result, and have the demangler defer its final allocation needs to the caller, and free its temporary data itself.

June 09, 2021
On 6/8/2021 9:50 PM, Andrei Alexandrescu wrote:
> Code in class destructors needs special typechecking and be restricted. IIRC, among other things it wasn't supposed to assume references to other class objects are valid. This has been discussed several times but never implemented.

Probably because nobody ever filed a bugzilla entry for it?
June 09, 2021

On Wednesday, 9 June 2021 at 21:44:20 UTC, Walter Bright wrote:

>

On 6/9/2021 7:01 AM, Steven Schveighoffer wrote:

>

I'm 99% sure we could have a nogc stack trace for InvalidMemoryOperationError if we had a nogc demangler. Everything else seems already nogc, just not fully marked.

I don't believe it would be hard to make a nogc demangler, even if it used malloc.

Even better, provide a "sink" parameter for the result, and have the demangler defer its final allocation needs to the caller, and free its temporary data itself.

The issue with the druntime demangler at the moment seems to be that it basically implements a state machine (pretty normal so far) then uses exceptions to backtrack on itself. The code is not good.

June 10, 2021

On Sunday, 6 June 2021 at 22:00:32 UTC, tsbockman wrote:

>

On Sunday, 6 June 2021 at 11:54:40 UTC, Mathias LANG wrote:

>

We currently have a random crash which seems to trigger when a
C++ object is destructed by the GC (to be precise: the GC
finalizes a class that holds an std::vector), but that
might just be our bindings...

extern(C++) class support is critically incomplete/buggy right now, even for basic usage that doesn't involve templates or multiple inheritance. Are you aware of these bugs?

Issue 21693 - extern(C++) class instance dtors are never called, breaking RAII:
https://issues.dlang.org/show_bug.cgi?id=21693

Issue 21690 - Unable to dynamic cast extern(C++) classes
(Dynamic casts of extern(C++) classes are silently lowered to unchecked static casts):
https://issues.dlang.org/show_bug.cgi?id=2169

Thanks for the pointers. I checked and I don't think we're using any of those, luckily. The first one, because we don't allocate those objects standalone, we always store them in another object, so their dtors are called (hence the bug).
We don't need dynamic cast (we have a few classes called from C++) so this is all fine for us.

The major bug that blocked us for a long time was https://issues.dlang.org/show_bug.cgi?id=20235 which was fixed in v2.096.0.

June 10, 2021
On Wednesday, 9 June 2021 at 02:37:34 UTC, Walter Bright wrote:
> On 6/6/2021 4:54 AM, Mathias LANG wrote:
> > https://github.com/dlang/druntime/pull/3476/files
>
> Frankly, the whole jazz with assert() went way off the rails. Assert should go directly to Jail, it should not pass Go or collect $200. All these layers it goes through is just madness.
>
> Allocating via the GC is in assert is just ridiculous, as the program is going to exit shortly anyway. There won't ever be a need to run a collection on it. Just malloc away and fuggeddabootet.
>
> These sorts of things are why I added the checkaction switch to bypass it and just do the simple, direct stuff.

Actually we use `-checkaction=context` by default in our unittest build and it allocates even more :)

But yeah, we should *not* consider `assert` as recoverable.
Which means we should not:
1) Catch them in contracts;
2) [Have unittests for assertion failures](https://github.com/dlang/phobos/blob/815a718c81f15e3155f95260b299ce1b7887664d/std/typecons.d#L3141-L3153)

Regarding point 2, we even have [special code](https://github.com/bosagora/agora/blob/fc210b69a6d8e9777935e6e368f318434e3df466/source/agora/test/Base.d#L118-L121) to handle this. Note that our application logs to a buffer in unittest mode, and we dump that buffer on assertion failure, so successful runs are silent and failing runs give you the full context.

> Throwing constructors is one of those things that makes a program very hard to reason about. I've debated with Andrei about requiring that constructors be nothrow. My advice is make them nothrow, i.e. design them so they cannot fail. There's not a single throwing constructor in DMD, and it's going to stay that way :-)

Last time I checked, there's *nothing* that was throwing in DMD?
June 10, 2021
On Thursday, 10 June 2021 at 00:39:44 UTC, Mathias LANG wrote:
> On Wednesday, 9 June 2021 at 02:37:34 UTC, Walter Bright wrote:
>> [...]
>
> Actually we use `-checkaction=context` by default in our unittest build and it allocates even more :)
>
> [...]

There aren't that many constructors in general, lots of static methods / construct after variable declaration-ing.
June 10, 2021

On Wednesday, 9 June 2021 at 21:44:20 UTC, Walter Bright wrote:

>

On 6/9/2021 7:01 AM, Steven Schveighoffer wrote:

>

I'm 99% sure we could have a nogc stack trace for InvalidMemoryOperationError if we had a nogc demangler. Everything else seems already nogc, just not fully marked.

I don't believe it would be hard to make a nogc demangler, even if it used malloc.

Even better, provide a "sink" parameter for the result, and have the demangler defer its final allocation needs to the caller, and free its temporary data itself.

Yep, the sink approach seems the most practical one, from my experience.
We use it a lot (for toString, serialization, hashing...) but it has one major drawback: It is restricted to the attributes that are set by the sink / function.
I talked about this when I mentioned my proposal for ADA at last DConf and I have a PR for a DIP I need to finish.
But for the demangler, we could just manually provide all possible overloads and call it a day.

Regarding the bigger point, I've been wanting to have more structured stack traces for a very long time, and that would also enable @nogc stack traces. Currently, object.Throwable.TraceInfo, the interface exposed by the runtime, is the other blocker, since any change would be a breaking change, its toString doesn't take a sink, and its opApply provides a formatted string, which forces allocation in opApply.
Currently, this is worked around by having a limited buffer (https://github.com/dlang/druntime/blob/751f5665a31ea0f150d71b22a9852abacc2f61ec/src/core/internal/backtrace/dwarf.d#L197-L239) but it just means we have a length limit for stack traces.

I really hope we can expose a struct like this to TraceInfo so that users can iterate on the stack trace themselves.

June 10, 2021

On Wednesday, 9 June 2021 at 14:01:39 UTC, Steven Schveighoffer wrote:

>

On 6/9/21 7:02 AM, Steven Schveighoffer wrote:

>

Come to think of it, an InvalidMemoryOperationError should use malloc instead of GC, then maybe we can get stack traces?

I delved into this a bit, trying to see where the GC allocations are happening. There are some functions that are not marked nogc that can be.

I got hung up on core.demangle.demangle.

It's used here: https://github.com/dlang/druntime/blob/751f5665a31ea0f150d71b22a9852abacc2f61ec/src/core/runtime.d#L830-L865

Would it be possible to just skip demangling in situations where the GC is unavailable?

Pasting the output through ddemangle isn't hard at all.