Skip to content

Demo const overflow#1883

Closed
tcharding wants to merge 3 commits intorust-bitcoin:masterfrom
tcharding:tmp-demo-const-overflow
Closed

Demo const overflow#1883
tcharding wants to merge 3 commits intorust-bitcoin:masterfrom
tcharding:tmp-demo-const-overflow

Conversation

@tcharding
Copy link
Copy Markdown
Member

@tcharding tcharding commented May 27, 2023

We are in luck, this performs as expected.

(This PR is not a merge candidate.)

/// * 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
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems super-complex and hard to deal with, I'd prefer it to be always panic.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume "always panic" will also translate into "won't compile" in const contexts?

Yes.

@tcharding
Copy link
Copy Markdown
Member Author

I have no opinion on the matter, I was just interested in how the language worked in this situation.

Copy link
Copy Markdown
Contributor

@yancyribbens yancyribbens left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@apoelstra
Copy link
Copy Markdown
Member

Ok, so assuming that @yancyribbens is correct, in summary

To "panic" in a constfn we have two options:

  • By triggering an array OOB we can get "panic at runtime, refuse compiling at compile-time" behavior
  • By triggering an overflow we can get the same, except that with debug mode we'll get a silent overflow

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 Result (usually defeats the purpose of a constfn by making the user unwrap shit) and silently doing the wrong thing (which ideally we'd avoid even though it represents a programming bug on the part of the caller).

@tcharding
Copy link
Copy Markdown
Member Author

tcharding commented May 29, 2023

(Following comment is not important for the discussion but just out of intereset, I agree that we should just use the OOB solution.)

I'm not sure why you say it silently overflows in const context release mode.

I have no clue why your demo on playground fails to build but this test runs (cargo --release test from_int_btc):

    #[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.)

@Kixunil
Copy link
Copy Markdown
Collaborator

Kixunil commented May 29, 2023

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.

@tcharding
Copy link
Copy Markdown
Member Author

oooo I see, another reason for the array out of bounds solution then eh.

@tcharding
Copy link
Copy Markdown
Member Author

We don't need this any more.

@tcharding tcharding closed this May 30, 2023
@yancyribbens
Copy link
Copy Markdown
Contributor

Here's a simple example of how const fn works with different compiler optimizations (release vs debug):
https://github.com/yancyribbens/const-overflow

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).

@yancyribbens
Copy link
Copy Markdown
Contributor

yancyribbens commented May 31, 2023

To "panic" in a constfn we have two options:

By triggering an array OOB we can get "panic at runtime, refuse compiling at compile-time" behavior

This doesn't seem to be possible with the current lint setup it seems. See test fail here (currently): #1870

By triggering an overflow we can get the same, except that with debug mode we'll get a silent overflow
debug mode panics, release mode can silently overflow (unless the compiler can determine an overflow will happen while comiling in which case the compiler can error).

Both of these will work with our MSRV of 1.48. We should prefer the former because it's simpler and more correct.

this doesn't currently seems possible because of the lints.

Non-panicking options include returning a Result (usually defeats the purpose of a constfn by making the user unwrap shit) and silently doing the wrong thing (which ideally we'd avoid even though it represents a programming bug on the part of the caller).

I agree that a silent fail should be avoided. The other option is to use panic() instead of oob work-around but only define the method from_int_btc() in 1.57+.

@apoelstra
Copy link
Copy Markdown
Member

I agree that a silent fail should be avoided. The other option is to use panic() instead of oob work-around but only define the method from_int_btc() in 1.57+.

This is an option, but it means that from_int_btc then can't be used to define compile-time BTC constants, which is exactly what we want a constfn for :)

@tcharding tcharding deleted the tmp-demo-const-overflow branch May 22, 2024 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants