https://issues.dlang.org/show_bug.cgi?id=22221
--- Comment #4 from Dennis <dkor...@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. --