-
-
Notifications
You must be signed in to change notification settings - Fork 667
make p-q illegal in @safe code #22348
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Thanks for your pull request, @WalterBright! Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "master + dmd#22348" |
|
Why is |
More like extended, for the purpose of detecting more bugs.
Great question. The answer is we need to decide what year to make it! |
Detecting bugs wasn't the purpose of
The current year is 2026. My assumption with the year scheme was that code that last compiled in that year would continue to compile with either the edition of the same year or the one before it. ie, code that compiled in 2025 should compile with either the 2024 or 2025 editions. Retroactively assigning random changes to old years will just mean I have to try random editions until something works, especially if the editions remain undocumented! |
|
I've added edition number as the first item on my edition planning list, let's move on. |
As @tgehr pointed out in the n.g., subtracting two pointers (p-q) is "undefined behavior" (UB) when the two pointer point to different memory objects. The trouble with that, is C backends can decide it is UB and then delete the code. UB can mean anything, so yes it can impair memory safety, and so making it an error is a valid behavior for @safe code. Easy workarounds remain:
|
Alternatively we could make the compiler cast the pointers to There are other options that Timon was suggesting in defining what it does to remove the UB. Removing a feature isn't the only option here. |
In order to delete the code, it would have to first prove that the pointers are to different memory objects at compile time. If we can't prove that, there's no problem here. If we CAN prove that, then we should simply issue an error instead of leaving that particular case undefined.
|
We cannot prove anything about aliasing to the same degree that a backend optimizer can. It won't be consistent with codegen. |
|
is void* p = ...;
size_t x = cast(size_t)p;to be considered unsafe? The above is isomorphic to the issue in this PR. |
|
@thewilsonator I don't see that as unsafe. |
|
@rikkimax DFA can neither prove q-p is safe nor prove that it is unsafe in the general case. |
|
Why not simply lower |
|
@Herringway Indeed, why not? That might be a great idea! But one problem remains. If p and q point to different objects, the result will be an unpredictable value. Is that really what we want to allow in @safe code? |
Sure. You're pretty much guaranteed a RangeError from using that index. I mostly just don't want to see this feature go away because it has helped me transition C code to |
At what point do D semantics end and C semantics go into effect? Integer overflow is UB in C. Does this mean integer addition will also be disallowed in If not, where exactly do you draw the line? |
|
There's enormous pressure in the industry to get compilers to check for more bugs in code. I've even seen attempts to get borrow checking in C++. If we don't improve our game, we'll get left behind. That said, @trusted and @System will let you do whatever you want. @Herringway you raise a good point. ImportC treats all imported C code as @System. I doubt much C code will compile as @safe as it stands now - C uses a lot of pointers, and @safe doesn't allow pointer arithmetic, and so I expect one must pretty much replace all the p-q expressions already. @CyberShadow yes integer overflow is UB. If the gcc/clang back ends detect it, they delete it. I ran into that recently where x<<64 did nothing (I expected the result to be 0). I don't have a good answer for what to do about this, so I'll just go with what D does now. There is sizable pressure to add overflow checks. |
Not a lot of people left to leave us behind these days.
Which is why people will simply slap those attributes on and call it a day, like you did with dmd. It's difficult enough to be
|
|
I've looked into UB and LLVM, and what ldc does. In short, pointer subtraction won't trigger the UB. https://llvm.org/docs/LangRef.html#sub-instruction https://llvm.org/docs/UndefinedBehavior.html void main()
{
void* a, b;
auto v = a - b;
}What matters is |
|
I've looked a bit into the left shift, resulting in removal rather than 0. If the optimizer can see that the shift amount is equal or larger to bitwidth of the integer it'll mark it as poison and it'll optimize out (with time travel support). This is fixable by doing: As long as this is defined ldc/gdc should have no trouble removing the UB for this stuff. |
|
What's the impetus of this idea, was there an actual bug related to pointer subtraction that would have been prevented by this? |
For 2024 edition.
discussion: https://www.digitalmars.com/d/archives/digitalmars/D/Should_p_-_q_be_disallowed_in_safe_code_380113.html