Remove a bunch of try_into().expect()#4200
Conversation
Pull Request Test Coverage Report for Build 13977619809Details
💛 - Coveralls |
|
oooo. Concept ACK. |
|
Forgot to say the warning is intentional for now - I think I'll fix that bug first before merging this. (Or anyone else can tonight, I don't think I'll do it today.) |
|
Nice. Here are two more tests I wrote while understanding the extension trait. #[test]
fn five_to_two() {
let slice = [1, 2, 3, 4, 5];
let (left, right) = slice.as_chunks::<2>();
assert_eq!(left, &[[1, 2], [3, 4]]);
assert_eq!(right, &[5]);
let (first, rest) = slice.split_first_chunk::<2>().unwrap();
assert_eq!(first, &[1, 2]);
assert_eq!(rest, &[3, 4, 5]);
let (rest, last) = slice.split_last_chunk::<2>().unwrap();
assert_eq!(rest, &[1, 2, 3]);
assert_eq!(last, &[4, 5]);
}
#[test]
fn get_array() {
let slice = [1, 2, 3, 4, 5];
let chunk = slice.get_array::<2>(0).unwrap();
assert_eq!(chunk, &[1, 2]);
// offset is an index of `T` not an index of chunks.
let chunk = slice.get_array::<2>(1).unwrap();
assert_eq!(chunk, &[2, 3]);
let chunk = slice.get_array::<2>(3).unwrap();
assert_eq!(chunk, &[4, 5]);
assert!(slice.get_array::<2>(4).is_none());
}At first I thought |
|
@jirijakes Yeah, I've seen someone mentioned that postmonomorphization errors only show up with |
|
@Kixunil, you're right. There is a related issue: rust-lang/rust#99682. So, |
e7c3070 to
1b22f7d
Compare
e3ed73d to
6bd2749
Compare
|
@jirijakes FTR I've seen a proposal to make |
|
@apoelstra do you want me to redo my PR or do it in a followup to save Tobin's ACK? |
|
@Kixunil can you force-push the PR? I think it'll be OK -- I should be able to ACK it and Tobin should be online before I sign off so I can start merging it. |
|
I need to run now (some unexpected stuff came up) but I think I'll be able to do it by the end of the day. |
|
|
||
| /// Tries to access a sub-array of length `ARRAY_LEN` at the specified `offset`. | ||
| /// | ||
| /// Returns `None` in case of out-of-bounds access. |
There was a problem hiding this comment.
Why not return an Error type with useful information instead of just None? Although that can be done later not needed with this PR.
There was a problem hiding this comment.
Because these are low-level primitives which don't have much information about the error, so ok_or is likely better but also this one is currently only used to implement APIs consistent with std which return Option so any such information would be a waste.
There was a problem hiding this comment.
I see. So besides mirroring std, since there is only one specific error then it's not informative to return why it error-ed it sounds like. Thanks, just looking to understand better the rational for when to return None and when to return an Error.
There was a problem hiding this comment.
One is in iterator - trying to go past the end means end of iteration. The other is get method which is similar enough to get on slices to warrant matching API. std has Option there not Result. While returning indices in error types is somewhat convenient in erroneous cases using get is usually an operation that's handled by the caller.
6dc30d2 to
474977f
Compare
| (left, right) | ||
| } | ||
|
|
||
| fn get_array<const ARRAY_LEN: usize>(&self, offset: usize) -> Option<&[Self::Item; ARRAY_LEN]> { |
There was a problem hiding this comment.
One is in iterator - trying to go past the end means end of iteration. The other is get method which is similar enough to get on slices to warrant matching API. std has Option there not Result. While returning indices in error types is somewhat convenient in erroneous cases using get is usually an operation that's handled by the caller.
I see, you're talking about when methods impl the trait. I guess doc comments here aren't need since it's implied by the trait.
There was a problem hiding this comment.
I was talking about where these methods are used.
|
Sorry, this needs another rebase. Process failure on my part -- I closed this tab because I was waiting for Tobin's ACK, and then I merged #4242 because it didn't conflict with any open tabs. |
474977f to
c1de142
Compare
|
Crap, these ridiculous conflicts are driving me crazy. I was thinking for a while of having a version control system that would store the entire source as a tree (AST + files + directories), not text and make formatting completely machine-generated. It'd make this kind of reformatting impossible (but still settable client-side; obviously, rustfmt would need some more tweaks) and many changes would become trivially mergable - e.g. Out of curiosity, does the idea sound appealing to you? Of course I'm not going to implement this any time soon, at least not in usable form, I'm just wondering if I'm the only one bothered by it. :) |
Yes, though I suspect you can get 95% of the way there with custom git merge strategies. And the last 5% probably is not worth the switching cost of learning a new VCS. In Bitcoin Core there is a notion of a "scripted diff" where if your diff is expressible in shell (e.g. Relatedly, it would also be nice to have a git diff driver that collapsed out scripted stuff so you don't have to wade through a bajillion renames to find the one real change.. |
Some amount yes but I did a bit of digging into it and I haven't found any documentation on how to implement them (just merge drivers) and the one merge driver I made for merging If we could just use non-nightly rustfmt it might be also worth applying it as a filter. Scripted diffs are nice but I'd love to see some tool that can do stuff like "rename this Rust variable". Anyway, this all is just entirely theoretical. |
|
Needs rebase after #4248. |
Previously we've used `try_into().expect()` because const generics were unavailable. Then they became available but we didn't realize we could already convert a bunch of code to not use panicking conversions. But we can (and could for a while). This adds an extension trait for arrays to provide basic non-panicking operations returning arrays, so they can be composed with other functions accepting arrays without any conversions. It also refactors a bunch of code to use the non-panicking constructs but it's certainly not all of it. That could be done later. This just aims at removing the ugliest offenders and demonstrate the usefulness of this approach. Aside from this, to avoid a bunch of duplicated work, this refactors BIP32 key parsing to use a common method where xpub and xpriv are encoded the same. Not doing this already led to a mistake where xpriv implemented some additional checks that were missing in xpub. Thus this change also indirectly fixes that bug.
These are defined in the BIP as invalid. The previous commit fixed a bug where invalid key was parsed as valid and this bug can be caught by these vectors. Therefore, if this commit is ordered before the last one the test will fail.
c1de142 to
437562e
Compare
|
Damn, this is exactly the kind of merge conflict that should be resolvable in a smarter version control... Anyway, rebased. |
|
Yeah. Super frustrating that we gotta manually re-apply renames like this. Queued for re-ACK and I'll also queue for merge since the range-diff from what Tobin ACKed is nearly trivial. (Though he may show up and sneak a new ACK in before my scripts are done running :)). |

Previously we've used
try_into().expect()because const generics werunavailable. Then they become available but we didn't realize we could
already convert a bunch of code to not use panicking conversions. But we
can (and could for a while).
This adds an extension trait for arrays to provide basic non-panicking
operations retutning arrays, so they can be composed with other
functions accepting arrays without any conversions. It also refactors a
bunch of code to use the non-panicking constructs but it's certainly not
all of it. That could be done later. This just aims at removing the
ugliest offenders and demonstrate the usefulness of this approach.