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
A stab at removing unsafes #109
Conversation
6361867
to
7bfcff6
Compare
Any remarks @boxtown ? |
Would it be possible to do some benchmarking on the updated functions? When I originally wrote this I was purposefully trying avoiding to avoid runtime bounds checking which I don't believe leads to UB (I'm assuming this is the reason for removing unsafes?) although at this point it may be the case that the Rust compiler is smart enough to compile away the bounds checks (I haven't really kept up with compiler improvements) Side note, are the formatting changes from running |
In my opinion the best selling point for removing unsafes is not necessarily to remove UB, but to easily convince others that there's no UB. I couldn't find anything that would appear to be UB, but if somebody has to choose a library and there's one with lots of unsafe blocks the choice is either to be negligent of them or to manually check them, and code review doesn't scale very well. Do you have a suggestion what an acceptable trade-off between performance and safety would be? My opinion is that a general purpose library should have no unsafe blocks, but I refrained from rewriting blocks that appeared to be deliberate and where I wasn't confident could be written safely without performance regressions. I've not yet benchmarked, but I'd be happy to do so if you give an idea what an acceptable benchmark would look like. |
Btw: In order to do my refactor I changed the function ranks such that it now has no side effects. The tests did not capture any mutation of self, is this a mistake or deliberate? If so, can I safely change
Formatting is one click away for me, I usually make it a habit to keep my diffs clean. |
I think the use of unsafe should be justified by benchmarks, not the other way around. Looking at the changes, it does not look like they affect performance critical code. I think for some of the changes here the bound checks can be optimized away, but not for all of them. Benchmarking would be nice to have (for example, employing criterion), but it seems as if it is currently not done for statrs. Personally, I think it makes sense to merge these changes and worry about benchmarking later. Note that this PR also contains some unrelated changes that are raising the minimally supported Rust version. I think this is reasonable, and the MSRV is not documented for statrs anyway. |
Dis-regard the formatting comment I missed the part where you were updating the constructors to use the short-hand.
The function used to do an in-place sort but it looks like it's no longer necessary from the changes in this PR. I'll try to do some benchmarking over the weekend to though so let's keep it in for now to avoid flip-flopping if there's an egregious drop in performance (probably unlikely) and we'll create a task to remove the Give me some time to do a little more thorough review of the PR (assuming you're mostly finished) otherwise should be good to merge |
My comment might not have been clear, removing mut was of course not necessary, so I put it back in for now in my personal tree. Probably best addressed with a different pr, as somebody might rely on the undocumented behaviour. Edit: I'd forgotten what I'd done a couple of days back and responded off the cuff. This parragraph is non-sensical. Side-effects don't exist anymore, but mut is still in. In order to alleviate your concerns I've begun benchmarking with criterion, so if you give me a day or two I'll see if I can get everything together. |
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.
On nightly there's partition_at_index that could be a candidate for most of the code in select_inplace
. I haven't yet tested, as to do this cleanly would probably involve newtyping [f64]
to guarantee no NaNs in the slice, which might be a good idea regardless.
I was not able to determine whether my changes had any performance impact, because I ran into what looks like undefined behaviour.
Based on the size of the index being dereferenced, the only reasonable explanation seems to be that |
There's one unsafe remaining in the computation of the factorial, which I want to refactor in the future. For now I'm finished. |
At line :569 in @boxtown |
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.
Looks good in general, great work thanks for doing this! Just left one comment, but it's not critical. We can squash and merge if you disagree
Agree and fixed. |
Thanks again for doing this work, I'll try to update the changelog and cut a release some time this weekend |
This pr is a work in progress to eliminate unsafes as far as possible.