Closed clint-white closed 2 years ago
The CI job failure looks like it is due to a network error while trying to download the crates.io
registry. Can you try it again?
@clint-white , thanks for the great work. I have re-run the CI jobs. I’m still in the process of learning the whole diffs. I’ll get back within a week.
@clint-white , Sorry for to be late. I'm back (finally).
The addition of a build script and conditional inclusion of certain features. The removal of the trait bound C: Compare
from the definition of struct BinaryHeap<T, C>. The removal of the license header from the top of the file binary_heap.rs.
The above sounds all reasonable to me.
Whether to increase the MSRV.
It's OK to increase MSRV. The PR is big, so I'll bump the crate version like 0.5.x.
Can you edit the CI file? https://github.com/sekineh/binary-heap-plus-rs/blob/fec9e24925bf40aeda3418288dd6948e7f760623/.github/workflows/rust.yml#L23
My guess is that the following lines will test the all conditional compilation.
include:
- os: ubuntu-latest
rust: nightly
cargo_args: ""
- os: ubuntu-latest
rust: 1.xx
cargo_args: ""
- os: ubuntu-latest
rust: 1.yy
cargo_args: ""
- os: ubuntu-latest
rust: 1.zz
cargo_args: ""
:
@sekineh , While I was reviewing the conditional compilation I noticed an error in one of the cfg
value names. I just added a commit fixing this.
You said its OK to increase the MSRV, but do you have a preference as to what to raise it to? It could stay at 1.36.0, or some of the special cases could be removed by increasing it. The first such case would be a From
impl at 1.41.0 which is not a large increase. After that, 1.52.0 is probably the next place but that is a bigger jump.
Once the MSRV is decided, I will make any necessary final adjustments based on that and then update the CI file to test any of the remaining versions with conditional compilation.
For MSRV, I think 1.52 is OK because older rustc users can always use older version of crates.
Another candidate is 1.56 which introduced edition 2021. Both is fine.
I went ahead and updated the CI file to include running the tests on versions of Rust where there is conditional compilation. For now this is based on an MSRV of 1.36.0. See if this is what you had in mind. I just saw that you want to increase to 1.52.0. I will make those changes and push and update when they are ready.
I updated the MSRV to 1.52.0, which allowed removing two of the Rust version checks. This now unconditionally sets deny(unsafe_op_in_unsafe_fn)
and implements From<BinaryHeap<T, C>>
for Vec<T>
.
Migrating to the 2021 edition would be nice. At that point the build.rs
script would not be needed (unless you want to later add conditional support for the methods newly stabilized in 1.63.0). It would also allow migrating the doc examples to use arrays instead of Vec
when constructing binary heaps, which is what is now done in std
.
But maybe that should be a another PR after this one is merged, but before releasing 0.5.0?
Looks good, I merge this first.
I updated the MSRV to 1.52.0, which allowed removing two of the Rust version checks. This now unconditionally sets
deny(unsafe_op_in_unsafe_fn)
and implementsFrom<BinaryHeap<T, C>>
forVec<T>
.
Thanks for removing conditional compilation.
Migrating to the 2021 edition would be nice. At that point the
build.rs
script would not be needed (unless you want to later add conditional support for the methods newly stabilized in 1.63.0). It would also allow migrating the doc examples to use arrays instead ofVec
when constructing binary heaps, which is what is now done instd
.But maybe that should be a another PR after this one is merged, but before releasing 0.5.0?
I agree, It’s a great idea to migrate to edition 2021 version.
This PR is an attempt to synchronize as much as possible the
BinaryHeap
in this crate with that in the Rust standard library as of 1.62.0.There have been numerous changes to the standard library implementation since this crate forked from Rust 1.24.0. A few of those have already been ported here, a few more propsed in #32, but there remain many more that have not, resulting in this admittedly very large PR.
I proceeded by simply comparing
binary_heap.rs
inbinary-heap-plus
0.4.1 with that inrust-lang/rust
as of version 1.62.0, and then began updating the former in steps consisting of what seemed to me to be related changes. What resulted was the following (at present) 18 commits. While the total diff introduced by this PR is somewhat overwhelming, the intent is that the individual commits are easier to follow as each is focussed on a particular kind of change (e.g., safety, documentation, adding#[must_use]
, etc.) Then, for each commit, I looked at the history of the changes in rust-lang/rust from 1.24.0 to 1.62.0 that were involved in those changes and documented the relevant upstream PRs in the commit messages I wrote here. I tried to be as complete as I could in doing that, but given the extent of that range of history there could be some that I missed.There are a few aspects of this PR that I want to highlight which I think warrant extra attention when reviewing it; these are elaborated below:
C: Compare<T>
from the definition ofstruct BinaryHeap<T, C>
.binary_heap.rs
.First, the build script came about as follows. A result of the upstream changes to use narrowly scoped
unsafe
blocks in the private sifting methods, together with the change to declare those sifting methods to beunsafe
fns, were compiler warnings from theunused_unsafe
lint since by default the body of anunsafe
function is treated as if inside an implicitunsafe
block already. This situation was avoided in #32 because that PR only introduced the narrowly scopedunsafe
blocks inside what are still declared to be safe functions. However, the sifting functions are clearly not safe to call; they performunsafe
operations without checking any safety invariants for those operations, instead passing that responsability on to their own callers. As I noted in this comment, upstream now declares the sifting functions asunsafe
. But doing so also means we now haveunsafe
blocks inunsafe
functions, and by default that produces theunused_unsafe
warnings.Rust 1.52.0 stabilized the lint
unsafe_op_in_unsafe_fn
; by setting this todeny
,unsafe
blocks are required for performing unsafe operations insideunsafe
functions, eliminating theunused_unsafe
warnings. This is the desired situation and what is done in Rust'sliballoc
. But it is only available starting with Rust 1.52.0. For earler versions of Rust, the best I could think of was to setunused_unsafe
to levelallow
to suppress these warnings.A build script to detect the compiler version was the best way I could think of to get rid of the
unused_unsafe
warnings, by conditionally setting#[deny(unsafe_op_in_unsafe_fn)]
on 1.52.0 or later, otherwise settting#[allow(unused_unsafe)]
. The alternatives seemed to be either to just ignore the warnings (sincecargo
will suppress these anyway when this crate is built as a dependency of another), or raise the MSRV to 1.52.0. I didn't like either of those, but please see if you agree or if you can think of another way to handle this.Once I added the build script for this purpose, I found a few other places where it was useful to check the compiler version; these are noted in the comments in the script as well as the relevant commits included here. This allows keeping the MSRV at 1.36.0, while still providing some more recent functionality available in the standard library which users might also expect here. But conditionally providing features based on the compiler version could perhaps become cumbersome in the future, so please consider whether this is something you really wish to support in this project in general as well as whether the particular places where I propose it are warranted in your opinion. Maybe it is better to keep the API consistent across all supported versions of Rust.
Second, regarding relaxing the trait bound
C: Compare<T>
on the definition ofBinaryHeap<T>
. I am not sure the reason why it was included in the first place; the analogous boundT: Ord
was not present in the standard library's code in 1.24.0 when this crate forked. TheT: Ord
bound was of course included on the impl block defining the methods ofBinaryHeap<T>
. But since the fork, upstream split that impl block into two so that the bound could be removed from those methods which do not need it. As a result, it is now somewhat difficult to simply diff the code here with that instd
and compare the methods which are present since those upstream have been reorded by the use of now two impl blocks. I decided to match closely the upstream code and thus split the single large impl block defining all of theBinaryHeap<T, C>
's methods into two, one with and one without theC: Compare<T>
bound. But of course that requires removing the bound from the struct definition. It also allows relaxing that bound on several trait implementations, again more closely aligning with the standard library.I do not think this is a backwards incompatible change since we are removing rather than adding a trait bound, and this crate is not yet at version 1.0 anyway, but nonetheless perhaps a minor version bump would be warranted anyway?
Third, upstream changes in
rust-lang/rust
since 1.24.0 removed the license headers from the various source files in favor of the license files located in the repository root directory. I went ahead and did the same here, but again this is something that you should make sure you are comfortable with before merging. I think that commit could easily be reverted if you wished to retain the license header inbinary_heap.rs.
The upstream PRs where this was discussed and decided are noted in the commit message.Finally, there is the question of whether to raise the MSRV. This is related to the first point where it was noted that build script allowed keeping the MSRV at 1.36.0. No change is required. However I will point out a few options for raising the MSRV that would eliminate some special cases and simplify maintenance, and you can see if you wish to go for any of these:
From<BinaryHeap<T, C>>
forVec<T>
; this would eliminate one of the special cases;unused_op_in_unsafe_fn
, the original motivation for adding the build script; by raising the MSRV to 1.52.0 and giving up on two things that require 1.56.0 one could forgoe a build script and any conditional compilation (at least for now).