This is a tough one to title. I've produced a minimal failing example here: GitHub - seen/fake_playground: Minimized example of failing implementation
I'm working with a project that consists of multiple crates in a virtual project. I've opted to use fake to help in generating test data, but I've got it in my head that I don't want to have test code accessible in my "production" crates. To that end, I've come up with a structure that consists of my "production" crates, and a test-utils crate. The production crates expose various types, and the test-utils crate implements fake::Dummy
for them by using a trait wrapper, for lack of a better description.
This approach may very well be questionable and we can discuss that, but I'm more curious about the error I've run into while attempting to build. If there's a solution great, but I'm more interested in understanding the cause.
The Setup:
prod_one
crate exposesProdOneData
prod_two
crate exposesProdTwoData
test_utils
crate depends on bothprod_one
andprod_two
and implementsfake::Dummy
on a "trait wrapper" to get around the orphan rules.
The Trouble Begins:
prod_one
dev-depends ontest_utils
(depending on itself transitively)- Using the
fake::Dummy
implementation fromtest_utils
forProdTwoData
works without issue. - Using the
fake::Dummy
implementation fromtest_utils
forProdOneData
(the type already declared in this crate) produces the compilation error below when building tests:
Compiling prod_one v0.1.0 (/Users/sean/src/fake_playground/prod_one)
error[E0277]: the trait bound `test_utils::Dummy<ProdOneData>: fake::Dummy<Faker>` is not satisfied
--> prod_one/src/lib.rs:16:48
|
16 | let Dummy::<ProdOneData>(data) = Faker.fake_with_rng(&mut rng);
| ^^^^^^^^^^^^^ the trait `fake::Dummy<Faker>` is not implemented for `test_utils::Dummy<ProdOneData>`, which is required by `Faker: fake::private::FakeBase<_>`
|
= help: the following other types implement trait `fake::Dummy<T>`:
test_utils::Dummy<ProdTwoData>
test_utils::Dummy<prod_one::ProdOneData>
= note: required for `Faker` to implement `fake::private::FakeBase<test_utils::Dummy<ProdOneData>>`
note: required by a bound in `fake_with_rng`
--> /Users/sean/.cargo/registry/src/index.crates.io-6f17d22bba15001f/fake-2.9.2/src/lib.rs:210:15
|
208 | fn fake_with_rng<U, R: Rng + ?Sized>(&self, rng: &mut R) -> U
| ------------- required by a bound in this associated function
209 | where
210 | Self: private::FakeBase<U>,
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Fake::fake_with_rng`
For more information about this error, try `rustc --explain E0277`.
error: could not compile `prod_one` (lib test) due to 1 previous error
This error is a bit confusing: Trait isn't implemented for ProdOneData
, suggest using one of these other types that does implement it, like prod_one::ProdOneData
.
I'm trying to understand where the breakdown is mostly for my own curiosity as it seems like most of the things I'm doing here are anti-patterns. I suspect:
- The transitive dependency on itself makes trait resolution on types owned by the crate unresolvable
- The method used by
fake
to makefake::Fake
unimplementable by using an internal private trait combined with a blanketimpl Fake for T {}
makes the implementation unresolvable.
I'm lacking the vocabulary to further unpack the error but it feels like some sort of "identity" of ProdOneData
from the current trait is somehow different from the ProdOneData
that is transitively referenced via the implementation in test_utils.