IndirectSignalReceiver

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,

pub fn function(&'view mut self) -> &'view mut F

Retrieves inner &mut F function ready to be used as SignalReceiver.

Trait Implementations§

§

impl<'c_view, F, R, C, P0, P1, P2> From<&'c_view mut F> for IndirectSignalReceiver<'c_view, &mut C, (P0, P1, P2), F>
where P0: Debug + FromGodot + 'static, P1: Debug + FromGodot + 'static, P2: Debug + FromGodot + 'static, F: FnMut(&mut C, P0, P1, P2) -> R + 'static,

§

fn from( value: &'c_view mut F, ) -> IndirectSignalReceiver<'c_view, &mut C, (P0, P1, P2), F>

Converts to this type from the input type.
§

impl<'c_view, F, R, P0, P1, P2> From<&'c_view mut F> for IndirectSignalReceiver<'c_view, (), (P0, P1, P2), F>
where P0: Debug + FromGodot + 'static, P1: Debug + FromGodot + 'static, P2: Debug + FromGodot + 'static, F: FnMut(P0, P1, P2) -> R + 'static,

§

fn from( value: &'c_view mut F, ) -> IndirectSignalReceiver<'c_view, (), (P0, P1, P2), F>

Converts to this type from the input type.
§

impl<'c_view, F, R, C, P0, P1, P2> From<&'c_view mut F> for IndirectSignalReceiver<'c_view, Gd<C>, (P0, P1, P2), F>
where P0: Debug + FromGodot + 'static, P1: Debug + FromGodot + 'static, P2: Debug + FromGodot + 'static, F: FnMut(Gd<C>, P0, P1, P2) -> R + 'static, C: GodotClass,

§

fn from( value: &'c_view mut F, ) -> IndirectSignalReceiver<'c_view, Gd<C>, (P0, P1, P2), F>

Converts to this type from the input type.

Auto Trait Implementations§

§

impl<'view, C, Ps, F> Freeze for IndirectSignalReceiver<'view, C, Ps, F>

§

impl<'view, C, Ps, F> RefUnwindSafe for IndirectSignalReceiver<'view, C, Ps, F>

§

impl<'view, C, Ps, F> Send for IndirectSignalReceiver<'view, C, Ps, F>
where F: Send, C: Send, Ps: Send,

§

impl<'view, C, Ps, F> Sync for IndirectSignalReceiver<'view, C, Ps, F>
where F: Sync, C: Sync, Ps: Sync,

§

impl<'view, C, Ps, F> Unpin for IndirectSignalReceiver<'view, C, Ps, F>
where C: Unpin, Ps: Unpin,

§

impl<'view, C, Ps, F> !UnwindSafe for IndirectSignalReceiver<'view, C, Ps, F>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.