Hello!
I have a project with two crates: a core
crate with common code and a cli
crate with "front-end" stuff. These two crates have duplicate test code, so I'd like to share it. I've been looking online and a common suggestion seems to be to add a third testutils
crate, which appeals to me because I also want to make the common test code public for consumers of the core
library.
So far, I've moved the common code from core
into testutils
, and then made core
have a dev-only dependency onto testutils
. For the most part, this seems to work... but I'm having some bizarre trouble with traits.
The core
crate provides a BuiltinCommand
trait. In testutils
, I have defined an InCommand
struct that implements such trait. This struct has a new
method that returns an Rc<Self>
:
// In the testutils crate...
pub struct InCommand {}
impl InCommand {
pub fn new() -> Rc<Self> { ... }
}
impl core::BuiltinCommand for InCommand { ... }
I want then to consume the InCommand
from the unit tests of the core
crate... but when I do so, I get this error:
error[E0277]: the trait bound `impl endbasic_core::exec::BuiltinCommand: exec::BuiltinCommand` is not satisfied
--> core/src/exec.rs:442:26
|
442 | .add_command(InCommand::new(Box::from(RefCell::from(golden_in.iter()))))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `exec::BuiltinCommand` is not implemented for `impl endbasic_core::exec::BuiltinCommand`
|
= note: required for the cast to the object type `dyn exec::BuiltinCommand`
... but the trait is implemented.
I tried changing the new
signature to return an Rc<impl BuiltinCommand>
but then I get errors of the form:
error[E0277]: the trait bound `impl endbasic_core::exec::BuiltinCommand: exec::BuiltinCommand` is not satisfied
--> core/src/exec.rs:442:26
|
442 | .add_command(InCommand::new(Box::from(RefCell::from(golden_in.iter()))))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `exec::BuiltinCommand` is not implemented for `impl endbasic_core::exec::BuiltinCommand`
|
= note: required for the cast to the object type `dyn exec::BuiltinCommand`
... which make me suspect that something is very wrong with my approach. Note the duality in exec::BuiltinCommand
vs. endbasic_core::exec::BuiltinCommand
in this error message. It seems as if Rust is picking this trait from two separate places and not realizing they are the same (which in my mind makes sense because the core
crate is still supplying the trait definition when its tests are built, so I can see how some confusion could arise there...
Any thoughts? Is my approach doomed?
Thank you!
PS: If this code samples are not specific enough, I can push the actual code as a broken commit somewhere. Let me know.