Implementing traits without repeating methods already defined on the struct - struct

I have a trait which only has one requirement, the presence of a methods len(&self) -> usize. It then provides implementations for a couple of new methods for the struct.
trait MyTrait {
fn len(&self) -> usize;
// ... some new functions with implementations
}
I'd like to implement this trait on std::collections::LinkedList which already has a method with that exact type signature. Currently, I'm doing this:
impl<T> MyTrait for LinkedList<T> {
fn len(&self) -> usize {
self.len()
}
}
I can then use the new methods defined by MyTrait on my LinkedList instances. However, it feels unnecessary to have to repeat the definition of the method like this, since the type signatures are identical. Is there a way to omit the re-definition of len in my trait implementation?

Is there a way to omit the re-definition of len in my trait implementation?
No, it is not possible.
You may be able to write a macro of some kind to write the code for you, but dealing with type parameters is annoying, to say the least.
See also:
How to call a method when a trait and struct use the same name?

Related

Re-boxing trait objects to generically implemented trait

So far I have rarely had issues with Rust's type inference, but I fear I don't quite understand the problem with the following code:
trait SpecificTrait {}
struct SpecificStruct;
impl SpecificTrait for SpecificStruct {}
trait GeneralTrait {}
impl<T: SpecificTrait> GeneralTrait for T {}
fn new_specific_box() -> Box<dyn SpecificTrait> {
Box::new(SpecificStruct {})
}
fn new_general_box(from_specific_box: bool) -> Box<dyn GeneralTrait> {
if from_specific_box {
new_specific_box()
} else {
Box::new(SpecificStruct {})
}
}
Playground
I assume it has to do with Rust probably still not supporting upcasting, though in this code SpecificTrait does not require GeneralTrait, but rather implements the more general trait generically over all types that implement SpecificTrait.
I am aware that the trait object types are different (which leads to the error in the above code), but I would expect type inference to acknowledge that every dyn SpecificTrait object should also be expressable as a dyn GeneralTrait object. However, I also cannot simply cast a Box<dyn SpecificTrait> as Box<dyn GeneralTrait>, either.
So, how would I (idomatically) have to go about re-expressing my Box<dyn SpecificTrait> as a Box<dyn GeneralTrait>?
I would expect type inference to acknowledge that every dyn SpecificTrait object should also be expressable as a dyn GeneralTrait object
But it isn't. A dyn SpecificTrait includes a pointer to the "virtual table" of function pointers to SpecificTrait methods, and you can't get a pointer to the corresponding virtual table for GeneralTrait from it. One of answers to the question you linked explains the problem for subtraits in detail, but
implements the more general trait generically over all types that implement SpecificTrait
makes this even worse. With subtraits, the methods of supertraits are at least present in the subtrait vtable (24- |methods of Self and supertraits in that answer). With the blanket implementation they aren't.
Another answer explained why you can't simply cast the trait object to get the result you want. However, there is a workaround:
impl SpecificTrait for Box<dyn SpecificTrait>{}
fn new_general_box(from_specific_box: bool) -> Box<dyn GeneralTrait> {
if from_specific_box {
Box::new(new_specific_box())
} else {
Box::new(SpecificStruct {})
}
}
In words, simply implement your specific trait for a boxed trait object, then box that. Not the most efficient, but it will work.
Playground
Maybe I did not get the deeper problem you are trying to express, but from the code, the reason why it is not compile is bacause the return type of the function fn new_specific_box() -> Box<dyn SpecificTrait> is Box<dyn SpecificTrait> where as you are expecting Box<dyn GeneralTrait>. These two are different types, so this code will not compile. If you can match the type, then it should be okay to compile.

Differences between 2 styles of default implementations in a trait?

There are 2 ways to provide methods for a Trait itself, Rustdoc distinguishes them by saying "provided methods" and impl dyn XXX. For example:
trait Trait {
fn foo(&self) {
println!("Default implementation");
}
}
impl Trait {
fn bar(&self) {
println!("Anonymous implementation?");
}
}
I noticed it when I was reading the documentation of Rust's failure crate.
What are the use cases for them? What are the differences?
The first snippet,
trait Trait {
fn foo(&self) {
println!("Default implementation");
}
}
implements a provided method on the trait. This method can be overridden by a trait implementation, but it does not have to be overridden.
The second snippet,
impl Trait {
fn bar(&self) {
println!("Anonymous implementation?");
}
}
implements an inherent method on a trait object of type dyn Trait. Method implementations for dyn Trait can only be called for trait objects, e.g. of type &dyn Trait. They can't receive self by value, since dyn Trait does not have a size known at compile time, and they can't be called on concrete types implementing Trait (including generic types with a Trait bound).
The modern notation is to write impl dyn Trait instead of impl Trait, and in fact this notation was one of the motivating examples for the introduction of the dyn keyword – the old syntax did not provide any clues as to what the semantics are, whereas the new syntax with the dyn keyword hints at the fact that this impl is only used together with dynamic dispatch.
A trait object is a fat pointer to an object implementing Trait, but the concrete type of the object is not necessarily known at compile time. The fat pointer contains a pointer to the object data, as well as a pointer to the virtual method table of the object type. The latter is used to dynamically dispatch to the correct trait implementation at runtime.
It is rather uncommon to use impl dyn Trait. Generally it's only useful if you want to make use of some dynamic type information, like downcasting to the actual type. The only traits with inherent methods on trait objects in the standard library are Any and Error.
In short: one can be overridden, and the other cannot.
When you define a trait, you define items that implementations of the trait may (or have to) override:
trait Trait {
fn foo(&self) {
println!("Default implementation");
}
}
impl Trait for i64 {
fn foo(&self) {
println!("i64 implementation: {}", self);
}
}
On the other hand, using impl Trait, you define inherent methods, which cannot be overridden:
impl Trait {
fn bar(&self) {
self.foo();
self.foo()
}
}
// Try:
impl Trait for i64 {
fn bar(&self) { ... } // error: bar cannot be overridden.
}
As a result, inherent traits methods act as the Template Method Pattern: they provide a canvas linking together one or multiple overridable method(s).
If you look at the failure crate that you linked, the method Failure::find_root_cause() states:
This is equivalent to iterating over iter_causes() and taking the last item.
You may consider those inherent methods to be convenience methods, methods providing an easy/intuitive interface for common tasks which can be accomplished manually... but are conveniently pre-defined.
Note: any inherent method could be implemented as a free function taking the trait as a first argument; however free functions cannot be called in method position.

Is it possible to get back the implementing type from a trait? [duplicate]

I have a collection of Trait, a function that iterates over it and does something, and then I would like to check the implementor type and if it is of type Foo then downcast it and call some Foo method.
Basically, something similar to Go's type-switch and interface conversion.
Searching around I found about the Any trait but it can only be implemented on 'static types.
To help demonstrate what I want:
let vec: Vec<Box<Trait>> = //
for e in vec.iter() {
e.trait_method();
// if typeof e == Foo {
// let f = e as Foo;
// f.foo_method();
//}
}
As you have noticed, downcasting only works with Any trait, and yes, it only supports 'static data. You can find a recent discussion on why it is so here. Basically, implementing reflection for references of arbitrary lifetimes is difficult.
It is also impossible (as of now, at least) to combine Any with your custom trait easily. However, a macro library for automatic implementation of Any for your trait has recently been created. You can also find some discussion on it here.
This isn't a Rust-specific problem, although the vocabulary may be a little different. The ideal way to solve a problem like this, not just with traits in Rust but in any language, is to add the desired behavior (foo_method in your example) to the abstract interface (Trait):
trait Trait {
fn trait_method(&self);
fn foo_method(&self) {} // does nothing by default
}
struct Foo;
impl Trait for Foo {
fn trait_method(&self) {
println!("In trait_method of Foo");
}
fn foo_method(&self) {
// override default behavior
println!("In foo_method");
}
}
struct Bar;
impl Trait for Bar {
fn trait_method(&self) {
println!("In trait_method of Bar");
}
}
fn main() {
let vec: Vec<Box<dyn Trait>> = vec![Box::new(Foo), Box::new(Bar)];
for e in &vec {
e.trait_method();
e.foo_method();
}
}
In this example, I have put a default implementation of foo_method in Trait which does nothing, so that you don't have to define it in every impl but only the one(s) where it applies. You should really attempt to make the above work before you resort to downcasting to a concrete type, which has serious drawbacks that all but erase the advantages of having trait objects in the first place.
That said, there are cases where downcasting may be necessary, and Rust does support it -- although the interface is a little clunky. You can downcast &Trait to &Foo by adding an intermediate upcast to &Any:
use std::any::Any;
trait Trait {
fn as_any(&self) -> &dyn Any;
}
struct Foo;
impl Trait for Foo {
fn as_any(&self) -> &dyn Any {
self
}
}
fn downcast<T: Trait + 'static>(this: &dyn Trait) -> Option<&T> {
this.as_any().downcast_ref()
}
as_any has to be a method in Trait because it needs access to the concrete type. Now you can attempt to call Foo methods on a Trait trait object like this (complete playground example):
if let Some(r) = downcast::<Foo>(&**e) {
r.foo_method();
}
To make this work, you have to specify what type you expect (::<Foo>) and use if let to handle what happens when the referenced object is not an instance of Foo. You can't downcast a trait object to a concrete type unless you know exactly what concrete type it is.
If you ever need to know the concrete type, trait objects are almost useless anyway! You probably should use an enum instead, so that you will get compile-time errors if you omit to handle a variant somewhere. Furthermore, you can't use Any with non-'static structs, so if any Foo might need to contain a reference, this design is a dead end. The best solution, if you can do it, is to add foo_method to the trait itself.

How do I use unsized types/traits in Rust? [duplicate]

This question already has answers here:
What is the correct way to return an Iterator (or any other trait)?
(2 answers)
Closed 6 years ago.
I have the following
trait T {}
type Iter = fn() -> Iterator<Item = T>;
fn func(iter: Iter) {
for a in iter() {
// ...
}
}
I would like iter to return an Iterator with move semantics, so I shouldn't have to return &Iterator. Problem is, Iterator is a trait, so it's unsized. The above code gets a compile error saying that Iterable does not satisfy the Sized trait because all local variables have to be statically sized.
On top of this, T is also a trait, therefore unsized, so I can't bind a to it either because it's unsized.
I'm new to Rust so this is really tripping me up. How do I use unsized types?
You probably shouldn't use unsized types at all here. Use generics instead:
trait Foo {} // T is a common name for type parameters, so use a different name
fn func<I, F>(iter: F) where I: Iterator, I::Item: Foo, F: FnOnce() -> I {
for a in iter() {
// ...
}
}
Check out the book chapters on generics and Fn* traits.
And by the way, accepting a function doesn't seem very useful, since you just call it once at the start. It seems much simpler to write the function like this:
fn func<I>(iter: I) where I: Iterator, I::Item: Foo {
for a in iter {
// ...
}
}
Unsized types only "work" if there is an additional level of indirection involved. Example:
trait Ttait {}
fn foo(x: Trait) {} // error: x would be unsized which is not allowed
fn bar(x: &Trait) {} // OK: x is just a reference
fn baz(x: Box<Trait>) {} // OK: x is just an "owning pointer"
But instead of using traits as types, you should probably prefer to use traits as bounds for type parameters of generic functions and structs:
fn generic<Type: Trait>(x: Type) {}
This is actually not a function but a family of functions. For each type Type that implements Trait the compiler will create a special version of generic if needed. If you have some value x of a concrete type that implements Trait and write generic(x) you will be invoking a function that is created especially for that type which is unsized. This is called "monomorphization".
So, traits have two uses. They act as unsized types (for trait objects, dynamic dispatch, dynamic polymorphism) as well as type bounds for generic code (static dispatch, static polymorphism). My suggestion would be to avoid trait objects if you can and prefer generic code.
Without knowing exactly what you're trying to do, let me show you one possibility:
trait Trait {
fn foo(&self);
}
fn func<'x,I>(iterable: I) where I: IntoIterator<Item = &'x Trait> {
for a in iterable {
a.foo();
}
}
struct Example;
impl Trait for Example {
fn foo(&self) {
println!("Example::foo()");
}
}
fn main() {
let arr = [Example, Example];
func(arr.iter().map(|x| x as &Trait));
}
This is an example which demonstrates both kinds of trait uses. func is generic over the kinds of iterables it takes but uses dynamic dispatch to invoke the right foo function. This is probably closest to what you were trying to do.
You could also go "full generic" (avoiding the dynamic dispatch for the foo calls. See delnan's answer) or "full dynamic" (making func agnostic about what kind of iterator it actually deals with at runtime). With more context we can probably make better suggestions.

Is it possible to cast a trait to the implementing struct? [duplicate]

I have a collection of Trait, a function that iterates over it and does something, and then I would like to check the implementor type and if it is of type Foo then downcast it and call some Foo method.
Basically, something similar to Go's type-switch and interface conversion.
Searching around I found about the Any trait but it can only be implemented on 'static types.
To help demonstrate what I want:
let vec: Vec<Box<Trait>> = //
for e in vec.iter() {
e.trait_method();
// if typeof e == Foo {
// let f = e as Foo;
// f.foo_method();
//}
}
As you have noticed, downcasting only works with Any trait, and yes, it only supports 'static data. You can find a recent discussion on why it is so here. Basically, implementing reflection for references of arbitrary lifetimes is difficult.
It is also impossible (as of now, at least) to combine Any with your custom trait easily. However, a macro library for automatic implementation of Any for your trait has recently been created. You can also find some discussion on it here.
This isn't a Rust-specific problem, although the vocabulary may be a little different. The ideal way to solve a problem like this, not just with traits in Rust but in any language, is to add the desired behavior (foo_method in your example) to the abstract interface (Trait):
trait Trait {
fn trait_method(&self);
fn foo_method(&self) {} // does nothing by default
}
struct Foo;
impl Trait for Foo {
fn trait_method(&self) {
println!("In trait_method of Foo");
}
fn foo_method(&self) {
// override default behavior
println!("In foo_method");
}
}
struct Bar;
impl Trait for Bar {
fn trait_method(&self) {
println!("In trait_method of Bar");
}
}
fn main() {
let vec: Vec<Box<dyn Trait>> = vec![Box::new(Foo), Box::new(Bar)];
for e in &vec {
e.trait_method();
e.foo_method();
}
}
In this example, I have put a default implementation of foo_method in Trait which does nothing, so that you don't have to define it in every impl but only the one(s) where it applies. You should really attempt to make the above work before you resort to downcasting to a concrete type, which has serious drawbacks that all but erase the advantages of having trait objects in the first place.
That said, there are cases where downcasting may be necessary, and Rust does support it -- although the interface is a little clunky. You can downcast &Trait to &Foo by adding an intermediate upcast to &Any:
use std::any::Any;
trait Trait {
fn as_any(&self) -> &dyn Any;
}
struct Foo;
impl Trait for Foo {
fn as_any(&self) -> &dyn Any {
self
}
}
fn downcast<T: Trait + 'static>(this: &dyn Trait) -> Option<&T> {
this.as_any().downcast_ref()
}
as_any has to be a method in Trait because it needs access to the concrete type. Now you can attempt to call Foo methods on a Trait trait object like this (complete playground example):
if let Some(r) = downcast::<Foo>(&**e) {
r.foo_method();
}
To make this work, you have to specify what type you expect (::<Foo>) and use if let to handle what happens when the referenced object is not an instance of Foo. You can't downcast a trait object to a concrete type unless you know exactly what concrete type it is.
If you ever need to know the concrete type, trait objects are almost useless anyway! You probably should use an enum instead, so that you will get compile-time errors if you omit to handle a variant somewhere. Furthermore, you can't use Any with non-'static structs, so if any Foo might need to contain a reference, this design is a dead end. The best solution, if you can do it, is to add foo_method to the trait itself.

Resources