RFC: Change what assert does on error

Dennis dkorpel at gmail.com
Tue Jul 8 20:17:20 UTC 2025


On Tuesday, 8 July 2025 at 19:18:39 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
> That simplification rewrite, is an optimization that can be 
> removed from the frontend.

"it can be removed" is irrelevant if we're talking about whether 
the optimization exists now.

> Right now it is contributing to the belief that Error will not 
> run cleanup. Which isn't true. It does.

Not when it bubbles through functions that have this nothrow 
optimization.
```D
import std.stdio;

// This program doesn't print "cleanup", unless you remove 
`nothrow`
void nothrowError() nothrow => throw new Error("error");
void main()
{
     try {nothrowError();}
     finally {writeln("cleanup");}
}

```

> Right, a nothrow specific optimization to me would mean that a 
> function is marked as nothrow and therefore an optimization 
> takes place because of it. The attribute comes before the 
> optimization.

That's exactly what I'm demonstrating: two functions, both with 
hidden bodies, only difference is the `nothrow` annotation, 
different code gen.

> That isn't what is happening here. The compiler is going 
> statement by statement, looking to see if in the execution of 
> that statement it could return via an Exception exception and 
> then when not present simplifying the AST. The attribute is 
> coming after the optimization.

Whether a function is `nothrow` determines the outcome of the 
statement control flow analysis that leads to the optimization. 
The tf.nothrow check is executed before the code path that does 
the AST rewrite, so you'd have to clarify what you means with 
"comes after". There's an indirection there, but that's 
completely irrelevant for this discussion. I really don't get 
what point you're trying to make. These are the facts:

1. `nothrow` currently affects code generation
2. `nothrow` currently affects whether `throw Error` skips 
finally blocks in try-finally blocks
3. `nothrow` can be written down in source code or inferred, 
which is treated the same
4. scope(exit) and destructor calls are lowered to try-finally, 
making them behave equivalently
5. All this logic currently exists in the frontend
6. It is possible to remove the nothrow optimization by changing 
frontend logic
7. There's a discussion going on whether that's desirable.

Do you disagree with any of these, or is there a different point 
you're trying to make?


More information about the Digitalmars-d mailing list