[GH-ISSUE #221] Avoiding conflicting features; allow multiple HTTP clients at once #71

Closed
opened 2026-02-27 20:22:56 +03:00 by kerem · 6 comments
Owner

Originally created by @marioortizmanero on GitHub (Jul 7, 2021).
Original GitHub issue: https://github.com/ramsayleung/rspotify/issues/221

Originally assigned to: @marioortizmanero on GitHub.

Something that has been troubling me for a while is that we have conflicting features in rspotify, but features in Rust must be additive:

  • Currently, the user can't enable multiple clients at the same time. If the features client-ureq and client-reqwest are enabled at the same time, they'll get hit by a compiler error warning them not to do so.
  • It should work like reqwest does for its blocking feature. It's not a toggle. Instead, it enables the blocking module so that you may use it in combination of the async one.

This is important because the Rust compiler may merge features of a crate when it's duplicated in the dependency tree. If your crate has a dependency somewhere on rspotify with reqwest and at the same time somewhere else rspotify with ureq, that will never possibly work because you can't merge client-ureq with client-reqwest. This is explained a few times in this post, for example here.

I thought this was more complicated than it actually is (still not easy). We actually have a base HTTP trait already, so what if we make the Spotify client generic over it? Here's a playground link that explains it: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=de0e9c0a596a5004b3e4af41071415d6. It might simplify a lot of things, really! The only downside is that the syntax to initialize the client will be a bit ugiler to specify the HTTP client.

Related issues:

Originally created by @marioortizmanero on GitHub (Jul 7, 2021). Original GitHub issue: https://github.com/ramsayleung/rspotify/issues/221 Originally assigned to: @marioortizmanero on GitHub. Something that has been troubling me for a while is that we have conflicting features in rspotify, but [features in Rust must be *additive*](https://github.com/rust-lang/cargo/blob/master/src/doc/src/reference/features.md#feature-unification): * Currently, the user can't enable multiple clients at the same time. If the features `client-ureq` and `client-reqwest` are enabled at the same time, they'll get hit by a compiler error warning them not to do so. * It should work like `reqwest` does for its `blocking` feature. It's not a toggle. Instead, it enables the `blocking` module so that you may use it in combination of the async one. This is important because the Rust compiler may merge features of a crate when it's duplicated in the dependency tree. If your crate has a dependency somewhere on rspotify with reqwest and at the same time somewhere else rspotify with ureq, that will never possibly work because you can't merge `client-ureq` with `client-reqwest`. This is explained a few times in [this post](https://www.reddit.com/r/rust/comments/ofm4nl/why_you_shouldnt_obsess_about_rust_features/), for example [here](https://www.reddit.com/r/rust/comments/ofm4nl/why_you_shouldnt_obsess_about_rust_features/h4dozda/). I thought this was more complicated than it actually is (still not easy). We actually have a base HTTP trait already, so what if we make the Spotify client generic over it? Here's a playground link that explains it: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=de0e9c0a596a5004b3e4af41071415d6. It might simplify a lot of things, really! The only downside is that the syntax to initialize the client will be a bit ugiler to specify the HTTP client. Related issues: * https://github.com/rust-lang/cargo/issues/4328 * https://github.com/fMeow/maybe-async-rs/issues/6 * https://github.com/fMeow/arangors/issues/37
kerem 2026-02-27 20:22:56 +03:00
Author
Owner

@marioortizmanero commented on GitHub (Jul 7, 2021):

By the way, this is completely unrelated to #215. You can still merge these and I'll work on this afterwards. There's no rush to close this issue as long as it's done before the new version; I'll do so when I have a bit of time.

<!-- gh-comment-id:875993585 --> @marioortizmanero commented on GitHub (Jul 7, 2021): By the way, this is completely unrelated to #215. You can still merge these and I'll work on this afterwards. There's no rush to close this issue as long as it's done before the new version; I'll do so when I have a bit of time.
Author
Owner

@marioortizmanero commented on GitHub (Jul 8, 2021):

I've made this repo to prove how this can be a problem, even with the new resolver: https://github.com/marioortizmanero/resolver-v2-conflict

<!-- gh-comment-id:876023457 --> @marioortizmanero commented on GitHub (Jul 8, 2021): I've made this repo to prove how this can be a problem, even with the new resolver: https://github.com/marioortizmanero/resolver-v2-conflict
Author
Owner

@bjorn3 commented on GitHub (Oct 15, 2021):

Would it be possible to publish two crates based on the same source code? One with the sync feature forcefully enabled and one with the async feature forcefully enabled? This is basically what rapier does to handle 2d/3d and f32/f64 with the same source. For example the 2d variant with f32 floats uses this Cargo.toml: github.com/dimforge/rapier@b59e813fd3/build/rapier2d/Cargo.toml (L40-L43) while the 3d variant with f32 floats uses: github.com/dimforge/rapier@b59e813fd3/build/rapier3d/Cargo.toml (L40-L43)

<!-- gh-comment-id:944418465 --> @bjorn3 commented on GitHub (Oct 15, 2021): Would it be possible to publish two crates based on the same source code? One with the sync feature forcefully enabled and one with the async feature forcefully enabled? This is basically what rapier does to handle 2d/3d and f32/f64 with the same source. For example the 2d variant with f32 floats uses this `Cargo.toml`: https://github.com/dimforge/rapier/blob/b59e813fd336419fcd44a78adc0b2c88b1d1cdca/build/rapier2d/Cargo.toml#L40-L43 while the 3d variant with f32 floats uses: https://github.com/dimforge/rapier/blob/b59e813fd336419fcd44a78adc0b2c88b1d1cdca/build/rapier3d/Cargo.toml#L40-L43
Author
Owner

@marioortizmanero commented on GitHub (Oct 15, 2021):

I tried to do that in a million ways, including how rapier does it in your links, but I ultimately gave up. I couldn't find any examples either, which made it harder. It's pretty cool that rapier managed to do it. I might have been doing it the wrong way because I didn't even know about required-features.

Anyhow, actually fixing the problem instead of using a hack like that will be better in the long run. No need for feature combinations when testing (just --all-features), nor documenting how it works and similars.

<!-- gh-comment-id:944612691 --> @marioortizmanero commented on GitHub (Oct 15, 2021): I tried to do that in a million ways, including how rapier does it in your links, but I ultimately gave up. I couldn't find any examples either, which made it harder. It's pretty cool that rapier managed to do it. I might have been doing it the wrong way because I didn't even know about `required-features`. Anyhow, actually fixing the problem instead of using a hack like that will be better in the long run. No need for feature combinations when testing (just `--all-features`), nor documenting how it works and similars.
Author
Owner

@marioortizmanero commented on GitHub (Jul 27, 2022):

This is super interesting and might actually fix our issue! https://blog.rust-lang.org/inside-rust/2022/07/27/keyword-generics.html

<!-- gh-comment-id:1196875444 --> @marioortizmanero commented on GitHub (Jul 27, 2022): This is super interesting and might actually fix our issue! https://blog.rust-lang.org/inside-rust/2022/07/27/keyword-generics.html
Author
Owner

@github-actions[bot] commented on GitHub (Jul 4, 2023):

Message to comment on stale issues. If none provided, will not mark issues stale

<!-- gh-comment-id:1619386286 --> @github-actions[bot] commented on GitHub (Jul 4, 2023): Message to comment on stale issues. If none provided, will not mark issues stale
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/rspotify#71
No description provided.