Conversation
| /// * In release mode non-const context: silently overflows | ||
| /// * In release mode const context: silently overflows | ||
| /// * In debug mode non-const context: panics | ||
| /// * In debug mode const context: fails to build |
There was a problem hiding this comment.
Seems super-complex and hard to deal with, I'd prefer it to be always panic.
There was a problem hiding this comment.
Well, it's consistent with the behavior for every other integer overflow, so "super complex" or not, it's something users have to deal with.
But sure, I'd also be happy using array indexing to always panic. (I assume "always panic" will also translate into "won't compile" in const contexts?)
There was a problem hiding this comment.
I assume "always panic" will also translate into "won't compile" in const contexts?
Yes.
|
I have no opinion on the matter, I was just interested in how the language worked in this situation. |
yancyribbens
left a comment
There was a problem hiding this comment.
I think there is more nuance than that. const context will fail to build in release mode also on stable:
https://play.rust-lang.org/?version=stable&mode=release&edition=2021&gist=b9a25406aad51d58286e2b8ed0603ef3
I'm not sure why you say it silently overflows in const context release mode.
|
Ok, so assuming that @yancyribbens is correct, in summary To "panic" in a constfn we have two options:
Both of these will work with our MSRV of 1.48. We should prefer the former because it's simpler and more correct. Non-panicking options include returning a |
|
(Following comment is not important for the discussion but just out of intereset, I agree that we should just use the OOB solution.)
I have no clue why your demo on playground fails to build but this test runs ( #[test]
#[cfg(not(debug_assertions))]
fn from_int_btc_overflow_in_release_mode_const_context() {
const AMOUNT: Amount = Amount::from_int_btc(u64::MAX);
let (overflowed_value, overflow) = u64::MAX.overflowing_mul(100_000_000);
assert!(overflow); // sanity check
let want = Amount::from_sat(overflowed_value);
assert_eq!(AMOUNT, want);
}(This test is different from when I first pushed this demo.) |
|
Oh, only now I looked at the example and the example triggers an explicit lint which is deny by default. There's no guarantee it'll work like this for every code. The code by @tcharding proves it that even something as simple as putting it into a function with a parameter will cause the lint to miss. |
|
oooo I see, another reason for the array out of bounds solution then eh. |
|
We don't need this any more. |
|
Here's a simple example of how const fn works with different compiler optimizations (release vs debug): From what I can determine, const fn will always fail to compile if the expression can be determined to overflow regarudless of compiler optimization flags such as the playground example. However, if what's compiled is a pointer to something on the stack that can't be determined at compile time, then release mode and debug mode work as @tcharding describe (as I show here). |
This doesn't seem to be possible with the current lint setup it seems. See test fail here (currently): #1870
this doesn't currently seems possible because of the lints.
I agree that a silent fail should be avoided. The other option is to use |
This is an option, but it means that |
We are in luck, this performs as expected.
(This PR is not a merge candidate.)