[Issue 22221] [dip1000] pure function can escape parameters through Exception

d-bugmail at puremagic.com d-bugmail at puremagic.com
Thu Feb 17 14:14:38 UTC 2022


https://issues.dlang.org/show_bug.cgi?id=22221

--- Comment #4 from Dennis <dkorpel at live.nl> ---
(In reply to Walter Bright from comment #3)
> Therefore, this fix will be both correct and break the least amount of code.

I'm not sure, what's left blocking the fix PR is 1 function in excel-D
(shouldEqual) and some Phobos unittests. It's unknown how much breakage results
from your proposal.

> For code that does break, the solution is to make a copy of the parameter,
> and throw the copy. This is workable since scope is not transitive.

How would you explain that special case to D users?

Let's consider the most obvious example:
```
void enforce(bool x, string msg) @safe pure
{
    if (!x)
        throw new Exception(msg);
}
```

The compiler will ask you to make a copy of the `msg` string for no good
reason. Now consider this variant that returns the first argument (like in
Phobos):

```
int* enforce(int* x, string msg) @safe pure
{
    if (!x)
        throw new Exception(msg);
    return x;
}
```

Because the return value has a pointer now, `msg` will not infer `scope` from
`pure` anyway, so the compiler either:
- allows it, meaning that changing the return type causes a weird unrelated
error about throwing `msg`
- still give an error, meaning you have to make a copy of `msg`, and still
cannot assign a `scope` string to the parameter!

Finally, consider giving an auto return type:
```
auto enforce(bool x, string msg)
{
    if (!x)
        throw new Exception(msg);
}
```

How are the attributes inferred? Possibilities are:
- impure @system
- impure @safe
- pure @system

Will this pick the `@safe` one? What if I explicitly specify `pure`, will it
infer `@system` then?

This looks like a special case that has a ripple effect of complexity, I can't
see this being a good idea.

--


More information about the Digitalmars-d-bugs mailing list