but in binary crate I need to do impl Tr for A<Type2>, and I cannot, since it won't allow me to impl foreign trait for a foreign struct (impl for type defined outside of crate). Is there a way around this?
I understand why such restriction exists for library crates, but not for binary crates, since nothing else can depend on them.
What if crate2 at some time added the dependency on crate1 and implemented Tr for A<Type2>? This would be breaking change, if your attempt was allowed.
I was reading the rust book yesterday and read about the newtype pattern. Wouldn't that work here?
here's an example of implementing Display on Vec
src/main.rs
use std::fmt;
struct Wrapper(Vec<String>);
impl fmt::Display for Wrapper {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[{}]", self.0.join(", "))
}
}
fn main() {
let w = Wrapper(vec![String::from("hello"), String::from("world")]);
println!("w = {}", w);
}
We’re allowed to implement a trait on a type as long as either the trait or the type are local to our crate. It’s possible to get around this restriction using the newtype pattern, which involves creating a new type in a tuple struct. (We covered tuple structs in “Using Tuple Structs Without Named Fields to Create Different Types” on page 86.) The tuple struct will have one field and be a thin wrapper around the type we want to implement a trait for. Then the wrapper type is local to our crate, and we can implement the trait on the wrapper.
That's true, but it's common enough for code in a binary to be moved at some point to a library, for example when you want to add a second binary. And making some code work or not work depending on the crate type could be a point of confusion.
Given the kinds of questions I see here often enough, I can pretty much guarantee that it would be confusing to especially newcomers. But as a seasoned Rustacean, I wouldn't find that particularly welcome either, as it would randomly cause my productivity to drop while trying to figure out why a crate that used to build and that I haven't made any changes to won't build anymore.
I ended up doing this, but then I have to use ugly .0 references everywhere to the content of the tuple struct. I wonder why Rust does not have struct embedding, like Go?
I think you can try implementing deref on your new type, so you can directly access the internal type's methods and stuff without the .0 everywhere. I'm sure it'll come with all sorts of limitations too, but better than nothing.
So I looked up Go's struct embedding (I do know go fairly well, even used it professionally to a minimal level. But never heard of struct embedding before lol)
With deref it seems like the behavior would be close to being similar to that right?
I impl'ed Deref, but ran into a problem with the borrow checker: one of the inner struct members itself contains references and gets mutated. It therefore required implementing DerefMut and that led to the changes in the traits (beyond adding .0 )that I did not want, so for now I left it with .0 access.