Reputation: 190
I'm trying to wrap a DST around a Rc
with the aim of cloning it and accessing it from various parts of the code but the following error appears on compilation.
Here is a minimal reproducible example of the error (playground):
use std::rc::Rc;
trait Trait<'a> {
fn return_hello(&self) -> &'a str;
}
impl<'a, F> Trait<'a> for F
where
F: Fn() -> &'a str
{
fn return_hello(&self) -> &'a str {
self()
}
}
impl<'a, T> Trait<'a> for Rc<T>
where
T: Trait<'a>
{
fn return_hello(&self) -> &'a str {
(**self).return_hello()
}
}
fn caller<'a, T>(t: T)
where
T: Trait<'a>
{
print!("{}\n", t.return_hello());
}
fn main() {
fn test1<'a>() -> &'a str {
"Hello from function"
}
let test2 = move || "hello from closure";
fn f<'a>() -> &'a str {
"Hello from Rc"
}
let test3: Rc<dyn Trait<'_>> = Rc::new(f);
caller(test1);
caller(test2);
caller(test3);
}
Gives:
error[E0277]: the trait bound `Rc<dyn Trait<'_>>: Trait<'_>` is not satisfied
--> src/main.rs:45:12
|
25 | fn caller<'a, T>(t: T)
| ------ required by a bound in this
26 | where
27 | T: Trait<'a>
| --------- required by this bound in `caller`
...
45 | caller(test3);
| ^^^^^ the trait `Trait<'_>` is not implemented for `Rc<dyn Trait<'_>>`
|
= help: the following implementations were found:
<Rc<T> as Trait<'a>>
Upvotes: 1
Views: 836
Reputation: 98486
Your impl for Rc<T>
has an implicit requirement that T: Sized
, as if you wrote:
impl<'a, T> Trait<'a> for Rc<T>
where
T: Trait<'a> + Sized //The latter is implicit
But when you want to apply it to a Rc<dyn Trait<'a>>
then the type T
is dyn Trait<'a>
, that is not Sized
, so it does not apply.
The solution is to add + ?Sized
to relax that requirement (playground):
impl<'a, T> Trait<'a> for Rc<T>
where
T: Trait<'a> + ?Sized
And now that you are into it you can add it to the other impl
too:
impl<'a, F> Trait<'a> for F
where
F: Fn() -> &'a str + ?Sized
so that it applies to dyn Fn() -> &'a str
, too.
Upvotes: 4
Reputation: 113
In the implementation of Rc<T>
for Trait
, T
have an implicit bound of Sized
(source) because of that, the implementations of Rc<T>
will only resolve to Sized
types. Simply telling that T
"may not be sized" will solve the problem, so add a ?Sized
.
impl<'a, T> Trait<'a> for Rc<T>
where
T: ?Sized + Trait<'a>
{
fn return_hello(&self) -> &'a str {
(**self).return_hello()
}
}
Upvotes: 1