Skip to content

Make closures convert to blocks automatically? #838

@madsmtm

Description

@madsmtm

When using methods with callbacks, it is common to create a block for the sole purpose of passing it to that callback. For example, in Winit we do:

unsafe {
    center.addObserverForName_object_queue_usingBlock(
        Some(name),
        None,
        None,
        &RcBlock::new(move |notification| {
            // ...
        }),
    )
}

It's a lot more rare to re-use the block, or choose a different kind of storage (like global_block!) for it, because the performance of that usually doesn't matter. It might be nice if we could avoid the &RcBlock::new(...), and simply pass the closure to the method?

I wouldn't want to just change the signature to impl Fn(&NSNotification), because that would mean we would always have to allocate a new block even if one isn't needed (and that goes against the spirit of this project).


One way to implement this would be to add a trait to convert from impl Fn(T) -> R to &Block<dyn Fn(T) -> R>:

pub trait Blockable<F: ?Sized> {
    type Storage: AsRef<Block<F>>;
    fn to_storage(self) -> Self::Storage;
}

impl<T, R, Closure: Fn(T) -> R> Blockable<dyn Fn(T) -> R> for Closure {
    type Storage = RcBlock<dyn Fn(T) -> R>;
    fn to_storage(self) -> Self::Storage {
        RcBlock::new(self)
    }
}

impl<T, R> Blockable<dyn Fn(T) -> R> for &Block<dyn Fn(T) -> R> {
    type Storage = Self;
    fn to_storage(self) -> Self::Storage {
        self
    }
}
// Similar for `RcBlock` and `&RcBlock` probably.

I'm yet unsure if this is worth it?

It would also conflict with rust-lang/rust#29625, we wouldn't be able to implement Fn for Block if that becomes possible in the future.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-block2Affects the `block2` crateA-frameworkAffects the framework crates and the translator for themenhancementNew feature or requestquestionThere is no such thing as a dumb one!

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions