Question About Dependency Resolution and Version Incompatibility

I am trying to build the vcard_tui project, and I received this error:

error[E0277]: the trait bound `impl ratatui::widgets::Widget + '_: Widget` is not satisfied because the trait comes from a different crate version
   --> src/tui/render/popup/property_note.rs:32:9
    |
32  |         textarea_with_block(state.textarea.borrow_mut(), state.selected.is(PropertyNoteSelected::Note), "Notes").widget(),
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Widget` is not implemented for `impl ratatui::widgets::Widget + '_`
    |
note: there are multiple different versions of crate `ratatui` in the dependency graph

I ran cargo tree and see that the base project was building with ratatui 0.25.0 and tui-textarea was building with ratatui 0.29.0.

I looked at how these dependencies were specified:

  • vcard_tui v0.1.2 specifies ratatui = "0.25.0" (here)
  • tui-textarea v0.4.0 specifies ratatui = ">=0.23.0, <1" (here)

Shouldn't 0.25.0 be compatible with >=0.23.0, <1? Why is Cargo not unifying the versions and causing me an error? Is there a way to solve this without upgrading the ratatui dependency in the base project or forking and modifying tui-textarea?

It is. (Though that's a questionable choice, to allow major versions that haven't been released yet and may have breaking changes.)

Cargo doesn't prefer unifying different major versions, and there is no way to tell it that they have to match in this case.

I have heard that this command will update the lockfile to make them match:

cargo update --package ratatui@0.29.0 --precise 0.25.0

2 Likes

Thank you for the response. Upon closer reading of the documentation, I found the last example here to apply to my case:

Generally, the following two packages will not have their dependencies unified because incompatible versions are available that satisfy the version requirements: Instead, two different versions (e.g. 0.6.5 and 0.7.3) will be resolved and built. The application of other constraints or heuristics may cause these to be unified, picking one version (e.g. 0.6.5).

# Package A
[dependencies]
rand = ">=0.6,<0.8.0"

# Package B
[dependencies]
rand = "0.6"  # meaning `>=0.6.0,<0.7.0`

In order to be unified, it appears that (from the first example above the one I quoted) "the following two packages will have their dependencies on bitflags unified because any version picked will be compatible with each other" [emphasis mine]. I find that surprising, but I understand that dependency resolution is in general full of compromises.

My remaining question is: does cargo actually view 0.23.0 and 0.25.0 as different major versions? Is there special handling for 0.y.z versions?

Yes: SemVer Compatibility - The Cargo Book

This guide uses the terms β€œmajor” and β€œminor” assuming this relates to a β€œ1.0.0” release or later. Initial development releases starting with β€œ0.y.z” can treat changes in β€œy” as a major release, and β€œz” as a minor release. β€œ0.0.z” releases are always major changes. This is because Cargo uses the convention that only changes in the left-most non-zero component are considered incompatible.