Reputation: 7740
I have a trait B
that defines a function which returns a reference to an object that implements the trait A
.
enum Error { }
trait A { }
trait B {
fn create_a<'a>() -> Result<&'a impl A, Error>;
}
However, when I try to compile I get the following error
error[E0562]: `impl Trait` not allowed outside of function and inherent method return types
--> src/lib.rs:10:37
|
10 | fn create_a<'a>() -> Result<&'a impl A, Error>;
| ^^^^^^
Upvotes: 1
Views: 687
Reputation: 76276
fn create_a<'a>() -> Result<&'a impl A, Error>;
There is no way to create a reference that will live as long as arbitrary lifetime without having an object that already has that lifetime and can act as its owner—and you have no object here at all, so this signature makes no sense.
For further argument I will assume you do have a self
argument with that lifetime (it probably needs to be mutable too): fn create_a<'a>(&'a mut self) -> Result<&'a impl A, Error>;
(note that since there is only one life-time that all mentioned references have, you can elide it: fn create_a(&mut self) -> Result<&impl A, Error>;
)
Now there are two options:
You can define the concrete type as member of that trait like
trait B {
type ImplA: A;
fn create_a(&mut self) -> Result<&ImplA, Error>;
}
This is not object-safe, but it will be statically dispatched.
You should be able to use the impl
type alias when implementing the trait to name the type if desired.
If you do want B
to be object-safe, use object reference, i.e.
trait B {
fn create_a(&mut self) -> Result<&dyn A, Error>;
}
this way dispatch to the return value is always dynamic, but you do that to allow dynamic dispatch to B::create_a
in the first place anyway.
Upvotes: 6
Reputation: 13430
There are multiple ways of returning a trait, all of them rely on some kind of indirection.
Box<A>
Rc<A>
/Arc<A>
&dyn A
T
The difference between 1, 2, 3 and 4 is static vs dynamic dispatching.
Upvotes: -1