While using boxed closures I ran into the following issue:
type Test = Rc<dyn Fn() -> i64>;
fn test_bad() -> Test {
Test::new(|| 42)
}
fn test_good() -> Test {
Rc::new(|| 42)
}
In the first case, I'm using the type alias to refer to the new
method, whereas I'm using Rc
directly in the second case.
In the first case, the compiler complains:
| Test::new(|| 42)
| ^^^ function or associated item not found in `Rc<(dyn Fn() -> i64 + 'static)>`
|
= note: the method `new` exists but the following trait bounds were not satisfied:
`dyn Fn() -> i64: Sized`
But the second case works just fine. Can somebody please explain the difference? Is there any way to refer to new
through the type alias or do I need to wrap it myself?
In test_good
, by calling Rc::new
on || 42
, you don't create an Rc<dyn Fn() -> i64>
, but an Rc<ClosureType>
, where ClosureType
is the unique type of the closure provided, and it is sized. Then, since the Rc<ClosureType>
is returned in a function that returns Rc<dyn Fn() -> i64>
, it implicitly casts it to a trait object.
test_bad
fails because instead of going from constructing an Rc
of a sized closure then casting it to an Rc
of an unsized trait object, it tries to directly construct an Rc
of an unsized trait object, which fails since all arguments to functions must be sized.
I don't think there's a direct way to refer to new
through the type alias, although you could very easily make your own:
fn new_test(func: impl 'static + Fn() -> i64) -> Test {
Rc::new(func)
}