Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unclear if block arguments must be required to implement Encode #434

Closed
mwcampbell opened this issue Apr 7, 2023 · 3 comments
Closed

Unclear if block arguments must be required to implement Encode #434

mwcampbell opened this issue Apr 7, 2023 · 3 comments
Labels
A-block2 Affects the `block2` crate question Further information is requested

Comments

@mwcampbell
Copy link

I noticed that block2 requires arguments to implement Encode, but it doesn't do anything with that trait on the arguments. Blocks have the same encoding regardless. So does this really need to be a requirement?

@madsmtm madsmtm added question Further information is requested A-block2 Affects the `block2` crate labels Apr 7, 2023
@madsmtm
Copy link
Owner

madsmtm commented Apr 7, 2023

The ABI that block2 builds upon allows for legacy reasons that blocks don't specify their encoding, though ideally they should (search for signature in that document). Since we can't easily generate them in const/static contexts yet (requires some form of const generics, see #70), we make use of the legacy option and don't provide the block's encoding, yet!

More importantly though, the bound is there to prevent accidentally passing types that are not FFI-safe, such as Vec<T>, or ZSTs like (). So mostly there to help with ensuring soundness.

Do you have a use-case for passing a non-Encode type?

@madsmtm
Copy link
Owner

madsmtm commented May 26, 2023

See also #442, in which an API using blocks is unusable because we don't yet set the encoding on blocks.

@madsmtm
Copy link
Owner

madsmtm commented Sep 3, 2023

I'm going to keep the Encode requirement on blocks because it is a great boon to safety.

If you want to pass a specific non-Encode type, you can do something like the following:

use block2::ConcreteBlock;
use objc2::encode::{Encode, Encoding};

#[repr(transparent)]
struct Helper(Box<u32>); // Or whatever type you need to pass across

unsafe impl Encode for Helper {
    // Or whatever encoding would be most descriptive for your type
    const ENCODING: Encoding = Encoding::Pointer(Encoding::Void);
}

let block = ConcreteBlock::new(|helper: Helper| {
    let my_type = helper.0;
    // Do whatever you need to do with your type
});
let block = block.copy();

let my_type = Box::new(5);
unsafe { block.call((Helper(my_type),)) };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-block2 Affects the `block2` crate question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants