function A
which take a function B
as parameter, again the function B
take function C
as parameter. I try the syntax like below, but this gives me an error:
fn a(b: impl Fn(impl Fn() -> ()) -> ()) -> () {
// ...
}
error[E0666]: nested `impl Trait` is not allowed
--> src/main.rs:2:21
|
2 | fn a(b: impl Fn(impl Fn() -> ()) -> ()) -> () {
| --------^^^^^^^^^^^^^^^-------
| | |
| | nested `impl Trait` here
| outer `impl Trait`
For some reason, I can't use &dyn
keyword:
fn a(b: impl Fn(&dyn Fn() -> ()) -> ()) -> () {
// ...
}
Are there another ways to do this?
And I don't know why nested impl Trait
cause an error.
Nested impl Trait doesn't work because it hasn't been specified or implemented yet. Also, because it isn't very useful given how other parts of Rust work.
fn a(b: impl Fn(impl Fn() -> ()) -> ()) -> ()
can be written using full generic syntax asSo what does that mean? It means that
B
is something callable that takes an argument of something else callable. But the important thing here is in the concrete types. Specifically,B
doesn't take any callable with a compatible signature, but specifically aC
. What is C? Well, that's the issue. If you calla
like this:then
C
is the type of the lambda's parameterf
, but that type is not known, since the parameterf
's type cannot be deduced from usage alone. But suppose that wasn't a problem, what would the body ofa
look like?Here we attempt to call
b
passing lambda. But the lambda's type isunnamed local lambda type
, notC
. SinceC
was passed in from the outside, it cannot be the type of a lambda local toa
. Simply put, unless you pass in aC
as an additional parameter toa
, there is nothing thata
has that it could pass tob
.What you apparently want is for
B
to be not a function object that can be called with someC
, but with anyC
. You want it to be a polymorphic function object. Rust doesn't support compile-time polymorphic function objects (the equivalent in Haskell would be aforall a. a -> IO ()
or similar). It only supports runtime polymorphic function objects.That's the job of
dyn
. Now you've said you can't use&dyn
, because you want to pass the function object to another thread. So instead, useBox<dyn>
: