On Monday, 5 April 2021 at 15:05:24 UTC, kdevel wrote:
You changed the definition of ``bar`` while the exception collector (``EC``) is meant to catch and collect an exception thrown from the *unmodified* function.
My point was that the code will work if you do explicitly what `lazy` does implicitly. If you don't want to modify `bar`, then it looks like this:
```D import std.stdio,std.typecons; struct EC { Exception [] ex; auto opAssign (X) (scope X f) if(is(X : void delegate()) || is(X : void function())) { writeln (__PRETTY_FUNCTION__); try return f (); catch (Exception e) ex ~= e; } } class E : Exception { this (string s) { super (s); } } void bar (int i) { if (i == 1) throw new E ("E"); } void main () { EC ec; ec = () { bar (1); }; // okay ec.writeln; } ```
It seems that the operator ``+=`` or ``~=`` may be better suited to express that intent. Rewriting this in terms of ``opOpAssign`` works as expected:
Given that you define the operation to append `~` to `ex` rather than overwriting it, `~=` is the best fit, I think.
However, `=` and `~=` should not treat `lazy void` parameters differently. They should either both work, or neither. I checked and this is actually a very old regression; both worked way back in DMD 2.061. So, I've filed a front-end bug report:
https://issues.dlang.org/show_bug.cgi?id=21802