-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Flags for unspecified behaviour #423
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
- Start Date: 2014-10-28 | ||
- RFC PR: (leave this empty) | ||
- Rust Issue: (leave this empty) | ||
|
||
# Summary | ||
|
||
Allow control of unspecified behaviour via compiler flags | ||
|
||
# Motivation | ||
|
||
Several things in Rust shouldn't have a well-defined result. However, | ||
safety and debugging, would like some well-defined option. | ||
|
||
# Detailed design | ||
|
||
There are several things in Rust that don't have a well-specified behaviour. | ||
Among them are: | ||
|
||
* Signed Integer arithmetic overflow | ||
* Shift amount overflow | ||
* Checked Array OOB indexing | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Out-of-bounds indexing is currently well-defined as failing. |
||
* Divide-by-Zero | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Division by zero is currently well-defined as failing. |
||
* LLVM UB in unsafe intrinsics | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a difference between undefined behaviour and something that's left unspecified. It is explicitly specified as being undefined behaviour. That means a program doing it is memory unsafe / incorrect and the language does not provide any guarantees about what will happen. |
||
* Unchecked Array OOB indexing (if we take #392 or some variant) | ||
|
||
In these cases, there are several things we could want to do – the primary | ||
options are task failure^H^H^H^H^H^H^Hpanic, aborting, undefined behaviour | ||
(which is unsafe except in the first 4 cases), and (in the former 2) | ||
returning a not-entirely-correct result (actually, with shift overflow, | ||
there are *2* such results – either x86-style masking of the shift count, | ||
or "correctly" returning 0/-1). | ||
|
||
Add a compiler flag that controls the choice, -S TYPE=ACTION | ||
|
||
Where TYPE is one of `signed_overflow`, `shift_overflow`, | ||
`checked_oob`, `divide_by_zero`, `unsafe_intrinsic`, `unsafe_oob` (and | ||
maybe more), and ACTION is one of "default", "fail", "undefined", | ||
or (with the first 2 options) "wraparound". Add "all" and "unsafe_all" flags | ||
to control the defaults (note that actually it is the safe options that | ||
allow unsafety in safe code, which can be confusing). Have the default | ||
be the current choice (currently we have `signed_overflow=wrap`, | ||
`shift_overflow=undefined`, `checked_oob=fail`, `divide_by_zero=fail`, | ||
`unsafe_intrinsic=undefined` and probably `unsafe_oob=undefined`) unless | ||
we make some different decision. | ||
|
||
For example, if we're debugging and want fail-fast, we could have | ||
`-S all=fail`, and until we do something with shift amounts people could want | ||
`-S shift_overflow=wrap`. | ||
|
||
# Drawbacks | ||
|
||
This would tempt people could use `-S checked_oob=undefined` and get 0wned. | ||
|
||
# Alternatives | ||
|
||
Also allow this on attributes. This would make it more likely to be | ||
mis-used. | ||
|
||
# Unresolved questions | ||
|
||
None currently. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually well-specified as wrapping around: http://doc.rust-lang.org/reference.html#behaviour-not-considered-unsafe
I suppose this prevents
x + 1 > x
and(2*x) / 2
from being optimized totrue
andx
respectively, and it might be interesting to investigate if such optimizations would really make existing Rust code faster. But for now it is well-specified.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that even if it wasn't mentioned in the reference, it would still be well-defined. The reference is not a language specification and does not cover most of Rust's semantics. A flaw in the reference does not change the definition of the language. The implementation is the closest thing to a specification right now.
It would be backwards incompatible to alter a guarantee that the compiler provides, even if it is not written down anywhere. Fixing undefined behaviour (not the same as unspecified behaviour) is not backwards incompatible. Any UB is an implementation soundness bug..