How to import an implementation of a trait from another module - rust

I have 3 modules
in lib.rs
Module where I'm trying to import impl Test for Block from tra.rs
mod tra;
mod stru;
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test() {
use tra::Test; // This doesn't works
let b = stru::Block::new(String::from("Text"));
println!("{}", b.p())
}
}
in stru.rs
Module where struct Block is wrote.
pub struct Block {
text: String
}
impl Block {
pub fn text(&self) -> &String {
&self.text
}
pub fn new(text: String) -> Block {
Block { text }
}
}
in tra.rs
Module where I'm implementing trait Test for Block
#[path = "stru.rs"]
mod stru;
use stru::Block;
pub trait Test {
fn p(&self) -> &String;
}
impl Test for Block {
fn p(&self) -> &String {
self.text()
}
}
I want to import an implementation from tra.rs into lib.rs. How would I do this?

First, you don't import the implementation. You import the trait and that's enough.
Your error is probably because you repeated the mod stru; in tra.rs. Don't. Ever. Define modules in lib.rs only (or submodules, but only if they're sub-sub-modules). Instead, just use it from the crate root:
use crate::stru::Block;
pub trait Test {
fn p(&self) -> &String;
}
impl Test for Block {
fn p(&self) -> &String {
self.text()
}
}

Related

How to create new objects of any type that is passed as an argument to a function in Rust

I need to be able to create new objects from any struct that implements some trait, is there a way to achieve that? Right now create_obj accepts objects of struct that implements trait, but in my program I don't have struct objects, they are implemented by user of a library.
trait Tr: {
fn new() -> Self;
}
struct St {}
impl Tr for St {
fn new() -> Self {
Self
}
}
// I want this function to be able to create any objects (that impl Tr) for me
fn create_obj<T: Tr>(t: T) -> Box<dyn Tr> {
Box::new(T::new())
}
#[cfg(test)]
mod tests {
use crate::{create_obj, St};
#[test]
fn it_works() {
// Here I want to pass a struct type that implements the trait, not the struct object
create_obj(St);
}
}
Above code obviously fails with:
^^ help: use struct literal syntax instead: `St {}`
For anyone struggling, here's how I did it:
trait Tr: {
fn new() -> Self;
}
struct St {}
impl Tr for St {
fn new() -> Self {
St {}
}
}
fn create_obj<U>() -> U
where
U: Tr
{
let state = U::new();
state
}
#[cfg(test)]
mod tests {
use crate::{create_obj, St};
#[test]
fn it_works() {
create_obj::<St>();
}
}

implementation of 'std::cmp::PartialEq' is not general enough

I am trying to use mockiato to mock a function that accepts an Option of my struct A but am receiving the following error.
error: implementation of `std::cmp::PartialEq` is not general enough
--> src\main.rs:45:14
|
45 | .expect_do_feature(|arg| arg.partial_eq(Some(&cfg)))
| ^^^^^^^^^^^^^^^^^ implementation of `std::cmp::PartialEq` is not general enough
|
= note: `std::cmp::PartialEq<std::option::Option<&'1 A>>` would have to be implemented for the type `std::option::Option<&A>`, for any lifetime `'1`...
= note: ...but `std::cmp::PartialEq` is actually implemented for the type `std::option::Option<&'2 A>`, for some specific lifetime `'2`
I would've thought the #[derive(PartialEq)] on the struct A would generate what was needed, but it looks like it doesn't quite do the full job. How do I implement what the compiler is telling me to do?
use std::collections::HashMap;
#[cfg(test)]
use mockiato::mockable;
#[derive(PartialEq)]
pub struct A {
pub data: HashMap<String, i32>,
}
impl A {
pub fn new() -> Self {
A {
data: HashMap::new(),
}
}
}
pub struct B;
#[cfg_attr(test, mockable)]
pub trait ProvidesFeature {
fn do_feature(&self, config: Option<&A>) -> Option<Vec<i32>>;
}
impl B {
pub fn new() -> Self {
B {}
}
pub fn do_feature(&self, config: Option<&A>) -> Option<Vec<i32>> {
Some(vec!())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mocking() {
let mut feature_mock = ProvidesFeatureMock::new();
feature_mock
.expect_do_feature(|arg| arg.partial_eq(None))
.times(1..)
.returns(Some(vec!()));
assert_eq!(vec![0; 0], feature_mock.do_feature(None).unwrap());
}
}
fn main() {
println!("Hello, world!");
}
In order to compile, I used mockiato = "0.9.5" in Cargo.toml. Don't forget to run this with cargo test if you attempt to reproduce.

Turn an upstream struct into a trait

I've got to interact with some upstream code that exposes an interface that could be a trait but is instead implemented directly on a struct. I'd like to pull out that interface into a trait so that my code can support alternative implementations. This can in fact be done, but isn't particularly ergonomic:
pub mod upstream_code {
pub struct Foo(());
impl Foo {
pub fn foo(&self) -> &'static str {
"foo"
}
}
impl Default for Foo {
fn default() -> Self {
Foo(())
}
}
}
mod my_code {
pub trait Foo {
fn foo(&self) -> &'static str;
}
impl Foo for super::upstream_code::Foo {
fn foo(&self) -> &'static str {
self.foo()
}
}
pub fn do_something<T: Foo>(t: T) {
println!("foo: {}", t.foo());
}
}
fn main() {
my_code::do_something(upstream_code::Foo::default());
}
Specifically, note that I have to regurgitate each function in wrapper form inside the impl Foo for super::upstream_code::Foo block.
There's Got To Be A Better Way! What's the most idiomatic way of handling this?

Simplify a long namespace for impl when importing the type would introduce ambiguity?

Is there a way to simplify namespace for the following code?
struct T {...}
impl<'a> From<A::B::C::D::Foo<'a>> for T {
fn from(x: A::B::C::D::Foo<'a>) -> Self {
T {...}
}
}
I don't want to use A::B::C::D::Foo in the current module as Foo might bring in namespace ambiguity.
Is there a way to temporarily/locally use A::B::C::D::Foo for the impl? It seems I can only do that within a function scope, rather than an impl scope.
Currently, my workaround is to use a dummy module.
struct T {...}
mod abc {
use super::T;
use A::B::C::D::Foo;
impl<'a> From<Foo<'a>> for T {
fn from(x: Foo<'a>) -> Self {
T {...}
}
}
}
If using a nested module is the canonical solution, is it possible to define an anonymous module since the module name is unimportant?
Note, I don't mind writing A::B::C::D::Foo once for impl, but since the type in from is the same as the one in impl From, I am looking for ways to NOT have to write the same A::B::C::D::Foo twice.
as Foo might bring in namespace ambiguity
You can rename the type when you import it to avoid ambiguity:
pub mod a {
pub mod b {
pub mod c {
pub mod d {
pub struct Foo;
}
}
}
}
struct T;
use a::b::c::d::Foo as UniqueName;
impl<'a> From<UniqueName> for T {
fn from(_: UniqueName) -> Self {
T
}
}
fn main() {}
You could also use a type alias:
type UniqueName = a::b::c::d::Foo;

Source trait is inaccessible

The situation is (severely simplified) this (playpen):
mod tokentree {
pub struct TokenTree;
mod serialize {
use std::collections::BTreeMap;
use super::TokenTree;
#[derive(Debug)]
pub struct InternStr;
pub trait InternStrsExt {
fn intern_strs(&self) -> BTreeMap<&str, InternStr>;
}
impl InternStrsExt for [TokenTree] {
fn intern_strs(&self) -> BTreeMap<&str, InternStr> { BTreeMap::new() }
}
}
pub use self::serialize::{InternStrsExt, InternStr};
}
use tokentree::*;
fn main() {
println!("{:?}", [TokenTree].intern_strs());
}
I get the following error (both on nightly and beta):
<anon>:20:22: 20:47 error: source trait is inaccessible
<anon>:20 println!("{:?}", [TokenTree].intern_strs());
^~~~~~~~~~~~~~~~~~~~~~~~~
My problem is that I don't even know what this is supposed to mean.
It needs a pub declaration. Also your declarations are all over the place. Recommended form is to stick your pub mod declarations first, then, use.
Here is the working example.
mod tokentree {
pub struct TokenTree;
pub mod serialize {
use std::collections::BTreeMap;
use super::TokenTree;
#[derive(Debug)]
pub struct InternStr;
pub trait InternStrsExt {
fn intern_strs(&self) -> BTreeMap<&str, InternStr>;
}
impl InternStrsExt for [TokenTree] {
fn intern_strs(&self) -> BTreeMap<&str, InternStr> { BTreeMap::new() }
}
}
pub use self::serialize::{InternStrsExt, InternStr};
}
pub use tokentree::*;
fn main() {
println!("{:?}", [TokenTree].intern_strs());
}
(playpen)
What happened here is that you stumbled upon following glitches:
https://github.com/rust-lang/rust/issues/18241
https://github.com/rust-lang/rust/issues/16264
You can't export your traits from a private module. That's why you need to change mod serialize into pub mod serialize. For example this playpen example demonstrates that exporting struct Export works, but un-commenting the println! will make it stop compiling, because we used a trait.
Tip: One thing that helps me with the visibility rules is to generate doc files and see which doc files are visible.

Resources