Explaining why something isn't safe
Steven Schveighoffer
schveiguy at gmail.com
Mon Aug 16 12:51:26 UTC 2021
This just came up in a discussion, and I've thought about this in the
past, so it might have already come up. But often times, you have some
code that you think will be `@safe`, but it gets inferred to be
`@system`. However, you can't tell where the safety violation is, so you
have this process where you make a clone of all the code, marking
everything as `@safe`, at all layers (even if they are in other
projects) until you find the culprit.
As was pointed out in the discussion, the compiler knows where it
decided to infer `@system`, would it be possible to force it to tell you
that?
An example:
```d
void foo() {}
auto bar(int x) {
foo();
return x * 2;
}
void main() @safe {
auto a = bar(5);
}
```
The result is:
```
Error: `@safe` function `D main` cannot call `@system` function `bar`
```
Whereas it would be nice to see the error:
```
Error: `bar` was inferred `@system` because it calls `@system` function
`foo`
```
Which should go all the way down to where the actual safety problem is.
This is a simple example that's easy to diagnose, but often times you
have a stack of template functions, and all you get is that the top
layer function is `@system`, instead of finding where it did the
unexpected inference at the bottom of the stack (or you forgot to mark a
`@safe` non-inferred function).
This happens with stuff like `format` or `writeln` which is composed of
dozens of layers of templates, and it's hard to find out which one is
the one doing the unexpected inference. I have run across sometimes the
inference giving up as well, which is a separate problem, but also
useful to diagnose.
It would be nice to have a pragma (or maybe this can be a compiler
diagnostic switch?) which shows the stack of inference that caused the
safety error. Or maybe it should just always be shown? After all, it is
an error, so no reason not to be fully descriptive.
-Steve
More information about the Digitalmars-d
mailing list