RFC: Change what assert does on error

Adam D. Ruppe destructionator at gmail.com
Tue Jul 8 20:37:55 UTC 2025


On Tuesday, 8 July 2025 at 14:05:25 UTC, Dennis wrote:
> So I take it opend changed that, being okay with the breaking 
> change?

opend reverted dmd's change of behavior introduced around 2018. 
Prior to then, dmd ran the finally blocks in all cases, then they 
changed it to "optimize" nothrow functions.

Now, I can't call this a regression per se, since the 
documentation said you can't expect the finally blocks to be run 
on Errors already even before that change, but this was a 
breaking change in practice - and not a simple compile error if 
you happened to combine certain features, it is a silent change 
to runtime behavior, not running code you wrote in only certain 
circumstances. Quite spooky.

Only if you dogmatically stick to the ideology that catching 
errors is unacceptable - despite the potential real world 
benefits of catching it, and the fact it does work just fine most 
the time even in upstream today (and historically, did in all 
cases) - can you justify this skipping of code as an optimization 
rather than a silent wrong-code compiler bug.

> Because @safe constructors of structs containing fields with 
> @system destructors will now raise a safety error even with 
> `nothrow`.

I've never encountered this, perhaps because upstream also worked 
this same way for many years, including through most the active 
development period of druntime, phobos, and arsd doesn't really 
concern itself with @safe nothrow attribute spam.

But if this did cause a compile error.... I'd prefer that to a 
silent runtime change, at least we'd be alerted to the change in 
behavior instead of being left debugging a puzzling situation 
with very little available information.

> ```D
> mutex.lock();
> arr[i]++;
> mutex.unlock();
> ```
>
> Instead of this:
>
> ```D
> mutex.lock();
> scope(exit) mutex.unlock();
> arr[i]++;
> ```

Like here, if the RangeError is thrown and the mutex remains 
locked with the first code sample, ok, you can understand the 
exception was thrown on line 2, so line 3 didn't run. Not 
pleasant when it happens to you, but you'll at least understand 
what happened.

But with the second sample, it'd take a bit, not much since it 
being an Error instead of Exception would jump out pretty 
quickly, but a bit of language lawyering to understand why the 
mutex is still locked in upstream D - normally, `scope(exit)` is 
a good practice for writing exception safe code.

> While I can't say I have the numbers to prove that its 
> performance is important to me, I currently like the idea that 
> scope(exit)/destructors are a zero-cost abstraction when 
> Exceptions are absent.

For what its worth, I kinda like the idea too, it did pain me a 
little to see the codegen bloat back up a lil when reverting that 
change. But....

>> Correctness trumps minor performance improvements.

yup.


More information about the Digitalmars-d mailing list