Struct IndirectSignalReceiver
pub struct IndirectSignalReceiver<'view, C, Ps, F>where
Ps: InParamTuple,
F: SignalReceiver<C, Ps> + 'static,{ /* private fields */ }
Expand description
A special “identity struct” which enables type inference while specifying various closures for connections.
If you want to write generic code that can handle different functions and forward them to TypedSignal
and ConnectBuilder
APIs,
you have to use SignalReceiver
in combination with this type. Please check its documentation for a detailed explanation.
§Background
Individual connect*
methods on TypedSignal
and ConnectBuilder
use the SignalReceiver
trait as a bound.
In addition to that, they have a rather complex bound involving IndirectSignalReceiver
:
impl<C: WithSignals, Ps: InParamTuple + 'static> TypedSignal<'_, C, Ps> {
pub fn connect<F>(&self, mut function: F)
where
for<'c_rcv> F: SignalReceiver<(), Ps> + 'static,
for<'c_rcv> IndirectSignalReceiver<'c_rcv, (), Ps, F>: From<&'c_rcv mut F>,
{ /* ... */ }
}
This second bound is necessary because rustc cannot infer parameter types in closures, when dealing with Fn/FnMut/FnOnce
traits abstracted
behind another trait (in our case SignalReceiver
). Without inference, it wouldn’t be reliably possible to pass |this, arg| { ... }
closures and would require the more verbose |this: &mut MyClass, arg: GString| { ... }
syntax.
To make type inference work in such cases, we need to specify concrete type, such as FnMut(...) -> R
or
<&mut F as Into<IndirectSignalReceiver<'_, MyClass, (Param0, Param1), Func>>>
. The dirty hack clever trick used here is to “smuggle” a
concrete Fn*
trait through IndirectSignalReceiver
. This forces rustc to resolve the concrete Fn*
type.
Prior designs included declarative macros to generate all connect*
functions with direct Fn*
bounds (not through SignalReceiver
).
This works well, too, but prevents users from extending the functionality through generic programming – they’d need to use macros, too.
§Usage within connect*
style methods
When using the trait bounds as described above, you can access the actual function in the following way:
IndirectSignalReceiver::from(&mut function)
.function()
.call((), args);
§Hidden impls
in this doc
To keep this documentation readable, we only document one variant of each impl From<F>
: arbitrarily the one with three parameters
(P0, P1, P2)
. Keep this in mind when looking at a concrete signature.
§Further reading
Implementations§
§impl<'view, C, Ps, F> IndirectSignalReceiver<'view, C, Ps, F>where
Ps: InParamTuple,
F: SignalReceiver<C, Ps> + 'static,
impl<'view, C, Ps, F> IndirectSignalReceiver<'view, C, Ps, F>where
Ps: InParamTuple,
F: SignalReceiver<C, Ps> + 'static,
pub fn function(&'view mut self) -> &'view mut F
pub fn function(&'view mut self) -> &'view mut F
Retrieves inner &mut F
function ready to be used as SignalReceiver
.