2

I am fairly new to rust and am trying to understand how best to create re-useable shared library components. I have a github repo named rust-libs that is setup as a cargo workspace. The project tree for this repo looks like this:

├── Cargo.lock
├── Cargo.toml
├── describable
│   ├── Cargo.toml
│   └── src
│       ├── describable.rs
│       └── lib.rs
└── health_check
    ├── Cargo.toml
    └── src
        ├── health_check.rs
        └── lib.rs

where the top-level Cargo.toml file contains:

[workspace]
members = [
    "describable",
    "health_check"
]

The Cargo.toml file in each member just defines the dependencies of that member and its version - e.g. describable/Cargo.toml:

[package]
name = "lib_describable"
version = "1.0.0"
authors = ["my-name <me@email.com>"]
edition = "2018"

[lib]
name = "lib_describable"
path = "src/lib.rs"

and health_check/Cargo.toml:

[package]
name = "lib_health_check"
version = "1.0.0"
authors = ["my-name <me@email.com>"]
edition = "2018"

[dependencies]
lib_describable = { path = "../describable" }

[lib]
name = "lib_health_check"
path = "src/lib.rs"

Note that I am naming the library with a lib_ prefix just to avoid any clashes with other rust libraries.

The lib.rs file in each workspace member just defines the public modules I want to export - e.g. describable/src/lib.rs:

pub mod describable;

The implementation for this is in describable/src/describable.rs:

pub trait Describable {
  fn describe(&self) -> String;
}

The implementation in health_check/src/health_check.rs is:

use lib_describable::describable::Describable;

pub trait HealthCheckable: Describable {
  fn check_health(&mut self) -> Result<(), String>;
}

When making any changes to a specific member, I always update its version number in its Cargo.toml file. CircleCI is used to automatically build this repo. If the build is successful, then the CircleCI job tags this repo with a multiple git tags (one per member in the workspace) and these tags are of the form <member-name>_<member-version-from-its-cargo-toml>_<git-short-commit-sha>, e.g. for the above two members it might tag the build with these tags:

describable_1.0.0_d2db9ff
health_check_1.0.0_d2db9ff

I then have a separate git repo that contains a rust binary that is built that makes use of these shared library members. The project refers to the shared library members in its Config.toml as follows:

...
[dependencies]
...
lib_describable = { git = "ssh://git@github.com/xxx/rust-libs.git", tag = "describable_1.0.0_d2db9ff" }
lib_health_check = { git = "ssh://git@github.com/xxx/rust-libs.git", tag = "health_check_1.0.0_d2db9ff" }
...
[[bin]]
name = "my-app"
path = "src/bin/main.rs"

xxx is just the obfuscated name of my github account. The file src/bin/main.rs in this project contains code of the form:

extern crate lib_describable;
extern crate lib_health_check;

use lib_describable::describable::Describable;
use lib_health_check::health_check::HealthCheckable;

pub trait MyDb: Describable + HealthCheckable {
  // some functions defined here that are not important for this issue
}

pub struct MySpecialDb { ... }

impl Describable for MySpecialDb {
  fn describe(&self) -> String {
    // returns a description of this DB
  }
}

impl HealthCheckable for MySpecialDb {
  fn check_health(&mut self) -> Result<(), String> {
    // performs some health check specific to this DB and returns either Ok(()) if its healthy or Err("...some error message...") if it is unhealthy
  }
}

impl MyDb for MySpecialDb { ... }

The problem I am finding is that the rust compiler does not seem to like the line impl HealthCheckable for MySpecialDb and reports an error of the form:

the trait bound `...::MySpecialDb: lib_describable::describable::Describable` is not satisfied

the trait `lib_describable::describable::Describable` is not implemented for `...::MySpecialDb`

note: perhaps two different versions of crate `lib_describable` are being used?rustc(E0277)

Is there something obvious that I am doing wrong here to cause this error?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Mufasa
  • 387
  • 1
  • 4
  • 13
  • I'm pretty sure that cargo thinks `lib_describable(git)` is different than `lib_health_check(git) -> lib_describable(path)`, you might be able to [override depenedencies](https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#overriding-repository-url) to get them in line – kmdreko Dec 07 '20 at 02:20
  • @kmdreko That section of the docs describes how to patch in other versions of a crate. I could not get that to work either with my scenario. Would really appreciate it if you could please sketch out how to fix this. – Mufasa Dec 07 '20 at 08:45

1 Answers1

0

Unfortunately it seems this is not a supported configuration in Cargo as can be seen from the responses I got for the issue I raised here: https://github.com/rust-lang/cargo/issues/8956

I have therefore converted my Cargo workspace repo into a Cargo lib repo where all my libs share a single version now.

Mufasa
  • 387
  • 1
  • 4
  • 13