Using two crates with conflicting requrements


#1

Hi,

I’m stuck upon a problem I can’t solve.
I’m using Rocket framework which requires serde/serde_derive < 1.0 and I also need chrono package who needs serde > 1.0.

Whatever I do I’m alwasy getting errors aboud missing trait implementation since those were moved/change while serde was getting stable release.

For example - with serde <1.0 I’m getting a lot of following errors:

     --> src/gpon.rs:34:16
       |
    34 | #[derive(Debug,Serialize,Deserialize)]
       |                ^^^^^^^^^ the trait `serde::Serialize` is not implemented for `chrono::DateTime<chrono::UTC>`
       |
       = note: required by `serde::ser::SerializeStruct::serialize_field`

When makeing upgrade to satisfy chrono I’m getting errors from Rocket code:

 --> src/main.rs:108:1
|108 | #[post("/makexml/<sn>", data="<values>")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `serde::de::Deserialize` is not implemented for `nccrest::pppoe::PPPoECredentials`
|
= note: required because of the requirements on the impl of `rocket::data::FromData` for `rocket_contrib::JSON<rest::pppoe::PPPoECredentials>`
= note: required because of the requirements on the impl of `rocket::data::FromData` for `std::result::Result<rocket_contrib::JSON<rest::pppoe::PPPoECredentials>, rocket_contrib::Error>`

When using head version of rocket.rs I’m getting another pile of erros regarding different Cookies implmentation…

Is there a way to tell compiler to use different libraries in different source .rs files so I can use [#[derive(Serialize,Deserialize)] either from serde 0.9. or 1.* ??

This kinds of errors still makes rust hard to use in production - way too many breaking changes everywhere.
But this one is beyond my skills to fix :slight_smile:


#2

Depending on what you need out of chrono you could downgrade it to 0.3.0 which is serde 0.9 compatible. To do so just change the version in your Cargo.toml to chrono = "=0.3.0" so that cargo won’t install the “semver compatible” 0.3.1.


#3

From what I understand, in general there is no way to resolve this and it could be seen as something lacking in the rust build system… on the other hand, it prevents you from including potentially TWO or more enourmous libraries in your project, which may have different bugs or behaviors or (in the case of some libraries) even conflict with eachother.

For something like serde, it will pretty much JUST increase the size of your binary – but imagine if it was a library that has to make system calls or hold some kind of global state or cooperation. All the library assumptions that it was the only one using the global state would be completely invalidated by the existance of another version of itself.

So ya, rust forces you to make sure you are using only libraries which have matching dependencies. This is one of the reasons getting libraries like serde to 1.0 is so important.


#4

This doesn’t help:
With following Cargo.toml:

serde = "0.9.15"
serde_derive = "0.9.15"
serde_json = "0.9.10"
[dependencies.chrono]
features = ["serde", "rustc-serialize"]
version = "0.3.0"

I’m still getting errors:

  --> src/gpon.rs:34:16
   |
34 | #[derive(Debug,Serialize,Deserialize)]
   |                ^^^^^^^^^ the trait `serde::Serialize` is not implemented for `chrono::DateTime<chrono::UTC>`
   |
   = note: required by `serde::ser::SerializeStruct::serialize_field`

Looks like chrono 0.3.0 is not compatible…


#5

Note the = sign inside the version string, the default if you don’t specify the requirement operator is the caret operator which would allow chrono 0.3.1 to be used when you specify 0.3.0. In your Cargo.toml you’ll want:

serde = "0.9.15"
serde_derive = "0.9.15"
serde_json = "0.9.10"
[dependencies.chrono]
features = ["serde", "rustc-serialize"]
version = "=0.3.0"

#6

Thanks for info ! I didn’t know about such rules regarding packages version.
It helped but now there is another package with similar problem…

error[E0277]: the trait bound `nccrest::config::Config: serde::de::Deserialize<'_>` is not satisfied
   --> src/main.rs:207:29
    |
207 |     let c: config::Config = toml::from_str(&cfgdata).unwrap();
    |                             ^^^^^^^^^^^^^^ the trait `serde::de::Deserialize<'_>` is not implemented for `nccrest::config::Config`
    |
    = note: required by `toml::from_str`

I’m pretty sure that after fixing this another issue pops-up :slight_smile: Why compiler can’t throw me all errors at a time ?
Now it throws some, I’m fixing those, and another round shows up :frowning:

I think I will just give up for some time until some basic libraries will stabilize.
I’ve spend more than 6 months writing small stuff, some FFI libs, and now I feel comfortable with writing code, I love language richness for types that allows me to put my design into structures and then such sh#* takes me days to solve :confused: Now I’m spending more time fighting wth dependencies that anything else …
Maybe another 3-6 months and this will be better.

Thanks for help !


#7

Do you think that this change of serde dependency in chrono qualifies as a breaking change, and the right thing to do for chrono authors would be to yank 0.3.1 and republish it as 0.4.0?


#8

Yeah, this is the problem with a major library that is a public dependency of many different libraries having a breaking change. There is an RFC in discussion that would move the error in these cases from a compile time error to a cargo build resolution time error which would hopefully help to identify these issues.

In this case I think the only real solution (without going down a winding path of trying to pin a whole lot of dependencies) would be to use an updated version of Rocket that has switched over to serde 1.0. From what I’ve seen of other crates I use that depend on serde there has been a very concerted effort to push tho 0.9 -> 1.0 update throughout the ecosystem. Looking at the Rocket issue tracker it appears to be supported on the current development version and they’re intending to release that “soon”. (Although from your comments in the OP you’ve already tried updating to that version and hit other incompatibilities, in this case I would call those relatively expected when using such an ambitious, non-stable, low-pre-1.0-version-number dependency). Judging by the quality of Rocket’s current guides I would hope they have a migration guide if there are any major incompatibilities.

If you do feel like continuing trying to get serde 0.9 working, you can use cargo-tree to see what is still depending on serde 1.0. cargo tree -i -p serde will probably tell you that there are multiple versions of serde in your project, then picking one version like cargo tree -i -p serde:1.0.8 will show you the pruned inverse dependency tree that is causing that package to be included, so you can then try to remove or change versions of dependencies to get rid of it.

It’s definitely a breaking change; it’s a semver major version bump of a public dependency. The chrono authors were aware of this and explicitly decided to break semver for this release because of some issues around the serde 0.8 -> 0.9 transition (there is a little description of them here). This was brought up as a chrono issue, which did include a proposal to yank 0.3.1; but it looks like they have decided not to do this.

Personally I disagree that breaking semver was the right call in this case, while having a chrono 0.4.0 release might have caused just as much breakage (from libraries trying to pass chrono types between a mixture of dependencies using 0.3.0 and 0.4.0) it would have made why the breakage is occurring more obvious. Although, Rust is still really lacking in user friendly tools for debugging issues like this; so in practice you likely know how to diagnose and fix either of these changes, or you have to dive into a real rabbit-hole learning how cargo resolves dependencies, how to read Cargo.lock and how to use cargo-tree. I’m quite hopeful that the public/private dependency RFC gets accepted and rolled out through existing crates, that should allow cargo itself to provide much better guidance on issues like this.


#9

After browsing github repos of another few crates and downgrading I was able to resolve all my dependency hell :slight_smile:
IMHO there are some crates that should be part of std lib or at least managed by the same group of people to smooth tansitions. It looks like serde 1.0 release breaks a lot of packages and when other maintainers can’t keep up with thier deps development this is happening.