On 06/05/2017 11:50 AM, Olivier FAURE wrote:
- But memory corruption is super bad, if a proved error *might* be
caused by memory corruption then we must absolutely throw the
potentially corrupted data away without using it.
- Besides, even without memory corruption, the same argument applies to
broken invariants; if we have data that breaks invariants, we need to
throw it away, and use it as little as possible.
[...]
My proposal for solving these problems would be to explicitly allow to
catch Errors in @safe code IF the try block from which the Error is
caught is perfectly pure.
In other words, @safe functions would be allowed to catch Error after
try blocks if the block only mutates data declared inside of it; the
code would look like:
import vibe.d;
// ...
string handleRequestOrError(in HTTPServerRequest req) @safe {
ServerData myData = createData();
try {
// both doSomethingWithData and mutateMyData are @pure
doSomethingWithData(req, myData);
mutateMyData(myData);
return myData.toString;
}
catch (Error) {
throw new SomeException("Oh no, a system error occured");
}
}
void handleRequest(HTTPServerRequest req,
HTTPServerResponse res) @safe
{
try {
res.writeBody(handleRequestOrError(req), "text/plain");
}
catch (SomeException) {
// Handle exception
}
}
The point is, this is safe even when doSomethingWithData breaks an
invariant or mutateMyData corrupts myData, because the compiler
guarantees that the only data affected WILL be thrown away or otherwise
unaccessible by the time catch(Error) is reached.
But `myData` is still alive when `catch (Error)` is reached, isn't it?
[...]
What do you think? Does the idea have merit? Should I make it into a DIP?
How does `@trusted` fit into this? The premise is that there's a bug
somewhere. You can't assume that the bug is in a `@system` function. It
can just as well be in a `@trusted` one. And then `@safe` and `pure`
mean nothing.