1tgr / rust-websocket-lite

A fast, low-overhead WebSocket client

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Updating tokio-util dependency in minor version broke semver

Xiretza opened this issue · comments

#270 updated the externally visible tokio-util dependency across a semver-incompatible boundary (0.6 to 0.7), and the affected crates were subsequently released without incrementing the major version. This breaks crates depending on them, e.g.:

$ cargo new foo
$ cd foo
$ echo -e 'hyper-websocket-lite = "0.5.0"\ntokio = {version = "1", features = ["rt"]}' >> Cargo.toml
$ cargo build
[...]
error[E0599]: no method named `framed` found for struct `MessageCodec` in the current scope
   --> /home/xiretza/.cargo/registry/src/github.com-1ecc6299db9ec823/hyper-websocket-lite-0.5.0/src/lib.rs:41:53
    |
41  |                 let client = MessageCodec::server().framed(upgraded);
    |                                                     ^^^^^^ method not found in `MessageCodec`
    |
   ::: /home/xiretza/.cargo/registry/src/github.com-1ecc6299db9ec823/tokio-util-0.7.3/src/codec/decoder.rs:178:8
    |
178 |     fn framed<T: AsyncRead + AsyncWrite + Sized>(self, io: T) -> Framed<T, Self>
    |        ------ the method is available for `MessageCodec` here
    |
    = help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
6   | use tokio_util::codec::decoder::Decoder;
    |

This is because hyper-websocket-lite 0.5.0 depends both on tokio-util 0.6 and websocket-codec, but the latest compatible websocket-codec version (0.5.2) now pulls in tokio-util 0.7 (due to the >= 0.6 constraint). Thus, hyper-websocket-lite's tokio_util::codec::decoder::Decoder (from tokio-util 0.6) is different from websocket-codec's tokio_util::codec::decoder::Decoder (from tokio-util 0.7).

The proper solution here is to yank all affected versions (i.e. websocket-codec and websocket-lite versions 0.5.1 and 0.5.2), republish the crates under a new major version, and avoid >= dependencies like the plague - they undermine the whole purpose of semver, since there's no way for you to actually guarantee that you will remain compatible with any breaking changes of the dependency.

Thanks for reporting this, I'll take a look and sort it out

In the foo repro above I don't see why cargo is choosing tokio-util 0.6 for websocket-codec and 0.7 for hyper-websocket-lite, but from reading https://doc.rust-lang.org/cargo/reference/resolver.html it looks like it's allowed to behave this way. (In the Cargo.lock in rust-websocket-lite itself, both get resolved to 0.7.)

It looks like my attempt in #270 to depend on either tokio-util 0.6 or 0.7 is not helpful and we should just have a semver bump of the crates in this repo. At this point there probably isn't a strong reason to still support tokio-util 0.6.