madsmtm / objc2

Bindings to Apple's frameworks in Rust
https://docs.rs/objc2/
MIT License
348 stars 40 forks source link

`derive` macros #55

Open madsmtm opened 2 years ago

madsmtm commented 2 years ago

We have a few traits that users has to implement manually, namely Encode, RefEncode, Message and the INS... traits. It would be nice if these could be automatically derived, but in essence we can't allow that because they are unsafe, and a derive macro wouldn't be able to uphold the required safety invariants.

#[derive(Encode)] (requested upstream in https://github.com/SSheldon/rust-objc/issues/52) specifically doesn't work because the user could create a #[repr(C)] struct which used e.g. [i8; 4] while the Objective-C side used int. Or *const u8 vs. c_void*; this is valid from a normal FFI-perspective, but Encode requires that the encodings match perfectly.

So I'm actually probably going to remove the existing objc2_foundation_derive helpers in this repo.

madsmtm commented 2 years ago

And my personal take: I really dislike the extra compilation cost and the complexity in implementing them; I'd any day rather use macro_rules!

madsmtm commented 2 years ago

objc2_foundation_derive is gone. I'll close this issue, but if someone wants to argue in favor of derive macros, feel free!

madsmtm commented 2 years ago

a derive macro wouldn't be able to uphold the required safety invariants.

Or *const u8 vs. c_void*; this is valid from a normal FFI-perspective, but Encode requires that the encodings match perfectly.

I'm finding, when converting huge amounts of code, that derived Encode and RefEncode might actually be useful... Maybe we can relax the safety requirements in them so that they don't have to be implemented correctly, only that they have to be correct FFI-wise? Or something... Will have to match the objc_msgSend functions in message/apple/...!

madsmtm commented 2 years ago

We could maybe also add a "old-compat" feature flag, which also implements Encode from the objc v0.2.7 crate; then crates from e.g. core-foundation-rs wouldn't need to choose between objc and objc2 support:

unsafe impl objc::Encode for T {
    #[inline]
    fn encode() -> objc::Encoding {
        objc::Encoding::from_str(T::ENCODING)
    }
}