units: Make from_int_btc_const take a 16 bit integer#4254
units: Make from_int_btc_const take a 16 bit integer#4254tcharding wants to merge 1 commit intorust-bitcoin:masterfrom
Conversation
|
Draft because patch 2 (trying to use the For more information about this error, try `rustc --explain E0391`.
error: could not compile `bitcoin-units` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...
error[E0391]: cycle detected when caching mir of `amount::unsigned::<impl at units/src/amount/unsigned.rs:72:1: 72:12>::from_sat` for CTFE
--> units/src/amount/unsigned.rs:105:5
|
105 | pub const fn from_sat(satoshi: u64) -> Result<Amount, OutOfRangeError> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: ...which requires elaborating drops for `amount::unsigned::<impl at units/src/amount/unsigned.rs:72:1: 72:12>::from_sat`...
--> units/src/amount/unsigned.rs:106:22
|
106 | if satoshi > Self::MAX_MONEY.to_sat() {
| ^^^^^^^^^^^^^^^
note: ...which requires simplifying constant for the type system `amount::unsigned::<impl at units/src/amount/unsigned.rs:72:1: 72:12>::MAX_MONEY`...
--> units/src/amount/unsigned.rs:82:5
|
82 | pub const MAX_MONEY: Self = Amount::from_int_btc_const(21_000_000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `amount::unsigned::<impl at units/src/amount/unsigned.rs:72:1: 72:12>::MAX_MONEY`...
--> units/src/amount/unsigned.rs:82:5
|
82 | pub const MAX_MONEY: Self = Amount::from_int_btc_const(21_000_000);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
= note: ...which again requires caching mir of `amount::unsigned::<impl at units/src/amount/unsigned.rs:72:1: 72:12>::from_sat` for CTFE, completing the cycle
note: cycle used when const-evaluating + checking `amount::unsigned::<impl at units/src/amount/unsigned.rs:72:1: 72:12>::ONE_BTC`
--> units/src/amount/unsigned.rs:78:5
|
78 | pub const ONE_BTC: Self = Amount::from_int_btc_const(1);
| ^^^^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information |
|
@tcharding without looking, my guess is that you've used |
f3335be to
cb8ef19
Compare
|
Ha, correct! Thanks man. |
Kixunil
left a comment
There was a problem hiding this comment.
Not objecting to the PR but I'd prefer changing the outer match for code clarity.
| /// If `whole_bitcoin` is greater than `21_000_000`. | ||
| #[allow(clippy::missing_panics_doc)] | ||
| pub const fn from_int_btc_const(whole_bitcoin: i32) -> Result<SignedAmount, OutOfRangeError> { | ||
| pub const fn from_int_btc_const(whole_bitcoin: i16) -> SignedAmount { |
There was a problem hiding this comment.
TODO: rename the function to from_i16_btc (or from_btc_i16)
(Can be postponed to a future PR.)
There was a problem hiding this comment.
Will leave for someone else.
units/src/amount/signed.rs
Outdated
| pub const fn from_int_btc_const(whole_bitcoin: i32) -> Result<SignedAmount, OutOfRangeError> { | ||
| pub const fn from_int_btc_const(whole_bitcoin: i16) -> SignedAmount { | ||
| let btc = whole_bitcoin as i64; // Can't call `into` in const context. | ||
| match btc.checked_mul(100_000_000) { |
There was a problem hiding this comment.
Checked multiplication is pointless and annoying here. If it can't overflow, just use the normal * operator.
units/src/amount/unsigned.rs
Outdated
| Ok(amount) => amount, | ||
| Err(_) => panic!("unreachable - 65536 BTC is within range") | ||
| } | ||
| None => panic!("unreachable - mul by 65536 cannot overflow a u64"), |
There was a problem hiding this comment.
Same issues in this section as above.
| pub const ONE_BTC: Self = SignedAmount::from_int_btc_const(1); | ||
| /// Exactly fifty bitcoin. | ||
| pub const FIFTY_BTC: Self = SignedAmount::from_sat_unchecked(50 * 100_000_000); | ||
| pub const FIFTY_BTC: Self = SignedAmount::from_int_btc_const(50); |
There was a problem hiding this comment.
Nice getting rid of these unchecked conversions!
cb8ef19 to
1f4e76d
Compare
| Err(_) => panic!("unreachable - 65536 BTC is within range") | ||
| } | ||
| None => panic!("unreachable - mul by 65536 cannot overflow a i64"), | ||
| let sats = btc * 100_000_000; |
There was a problem hiding this comment.
Did you mean to do this in previous commit?
There was a problem hiding this comment.
Bother, my bad. Thanks man
The `from_int_btc_const` constructors are specifically designed for easily creating amount types in const context but currently they return an error which is annoying to handle in const context. If we make the `whole_bitcoin` parameter a 16 bit integer this gives us a nicer const constructor with the downside that it can only create values upto a maximum of - unsigned: 65_536 - signed: 32_767 That is plenty high enough for most use cases. Then use the new `from_int_btc_const` in associated consts. Note that because `from_sat` checks max (and min) values we must define max and min from sats directly.
1f4e76d to
dfc2562
Compare
|
I just squashed the whole thing into a single patch because I'm lazy right now. |
|
I'm going to make another PR building on this one, and maybe we can just merge that instead. |
|
@tcharding ok if we close this in favor of #4256? It has a copy of this commit except that I changed the formatting on two lines ( In any case I'll hold off on merging til you respond. |
|
OK, I'll wait with review of #4256 until Tobin responds too. Though since that one has no ACKs, how about you just rebase it on top of this one? I could then review it right away and this one can go in. (Though I think it messes up hash commits unles fast forward merge is used and we don't do those here? Maybe we should consider pijul, LOL.) |
I can do that, but then I can't do |
|
Close/merge either one man. For the record you are always welcome to do surgery on my PRs and/or patches taking any bits you like. No attribution needed ever. Code is a liability to me not an asset - if it merges under your name hopefully if/when its found buggy I'll forget that I wrote it and think the bugs were yours. Leaving you to close in case you need it open, so I don't have to think about the process. |
Lol!! |
2958521 amount: remove from_sat_unchecked (Andrew Poelstra) d0d7a15 amount: move MIN/MAX constants and constructors inside the privacy boundary (Andrew Poelstra) 004d073 amount: return i64 from parse_signed_to_satoshi (Andrew Poelstra) 3370c14 amount: stop using from_sat_unchecked in tests (Andrew Poelstra) 05c8b04 tests: replace Amount::from_sat_unchecked with from_sat.unwrap (Andrew Poelstra) beaa2db amount: add from_sat_i32 and from_sat_u32 methods for small constants (Andrew Poelstra) 82d9d1a amount: rename `from_int_btc_const` unctions to hungarian ones (Andrew Poelstra) 2ec1c2a units: Make from_int_btc_const take a 16 bit integer (Tobin C. Harding) Pull request description: This does some followups to #4157. It pulls in #4254, which changes the signature of `Amount::from_int_btc_const` and also replaces a `checked_mul` which can't ever fail with a `*`. It then renames `from_int_btc_const` to `from_btc_u16`/`from_btc_i16` as appropriate, since these names reflect what the function does. It also adds an analogous method for making `Amount`s from sats rather than BTC. Then it systematically removes every instance of `from_sat_unchecked`. There wind up being 7 instances in tests that I just added unwraps() to, plus one instance where we had `let sat = Amount::from_sat_unchecked` which I also added an unwrap() to. In the real code, there was one instance (`Amount::to_signed`) where I needed to add an `expect`. Every other instance I was able to remove, by refactoring logic to use the error case as appropriate. ACKs for top commit: tcharding: ACK 2958521 Kixunil: ACK 2958521 Tree-SHA512: e2c2eb19acdd60da5524f6700e66c140b8e113bec7f2418a2505aeefdbf742eff216fb580891a3ea53255156786f5a6b365b8fb6553e60e42b18d4115d705dd2
The
from_int_btc_constconstructors are specifically designed for easily creating amount types in const context but currently they return an error which is annoying to handle in const context. If we make thewhole_bitcoinparameter a 16 bit integer this gives us a nicer const constructor with the downside that it can only create values upto a maximum ofThat is plenty of corn for most use cases.