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

Add Option return types to Objective-c for nullability attributes #1876

Open
simlay opened this issue Aug 18, 2020 · 0 comments
Open

Add Option return types to Objective-c for nullability attributes #1876

simlay opened this issue Aug 18, 2020 · 0 comments

Comments

@simlay
Copy link
Contributor

simlay commented Aug 18, 2020

This is a subtask for #109 and I've been trying just implement it for a while but it's become clear that it's annoyingly nontrivial. Part of me writing this issue is so that it's at least documented.

Input Objc Header

// bindgen-flags: --objc-extern-crate -- -x objective-c
// bindgen-osx-only

@interface Bar
@end

@interface Foo
- (Bar* _Nullable)methodReturningBar;
- (Bar* _Nonnull)methodReturningNonnullBar;
@property (readonly, nonnull) Bar *nonnullBar;
@property (nullable, readonly) Bar *nullableBar;
@end

Bindgen Invocation

$ bindgen input.h --objc-extern-crate -- -x objective-c

Actual Results

/* automatically generated by rust-bindgen 0.54.1 */

#[macro_use]
extern crate objc;
#[allow(non_camel_case_types)]
pub type id = *mut objc::runtime::Object;
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct Bar(pub id);
impl std::ops::Deref for Bar {
    type Target = objc::runtime::Object;
    fn deref(&self) -> &Self::Target {
        unsafe { &*self.0 }
    }
}
unsafe impl objc::Message for Bar {}
impl Bar {
    pub fn alloc() -> Self {
        Self(unsafe { msg_send!(objc::class!(Bar), alloc) })
    }
}
impl IBar for Bar {}
pub trait IBar: Sized + std::ops::Deref {}
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct Foo(pub id);
impl std::ops::Deref for Foo {
    type Target = objc::runtime::Object;
    fn deref(&self) -> &Self::Target {
        unsafe { &*self.0 }
    }
}
unsafe impl objc::Message for Foo {}
impl Foo {
    pub fn alloc() -> Self {
        Self(unsafe { msg_send!(objc::class!(Foo), alloc) })
    }
}
impl IFoo for Foo {}
pub trait IFoo: Sized + std::ops::Deref {
    unsafe fn methodReturningBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, methodReturningBar)
    }
    unsafe fn methodReturningNonnullBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, methodReturningNonnullBar)
    }
    unsafe fn nonnullBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, nonnullBar)
    }
    unsafe fn nullableBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, nullableBar)
    }
}

The importart parts are the functions:

pub trait IFoo: Sized + std::ops::Deref {
    unsafe fn methodReturningBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, methodReturningBar)
    }
    unsafe fn methodReturningNonnullBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, methodReturningNonnullBar)
    }
    unsafe fn nonnullBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, nonnullBar)
    }
    unsafe fn nullableBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, nullableBar)
    }
}

Expected Results

Ideally, this should return Options around things that can be null

pub trait IFoo: Sized + std::ops::Deref {
    unsafe fn methodReturningBar(self) -> Option<Bar>
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, methodReturningBar)
    }
    unsafe fn methodReturningNonnullBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, methodReturningNonnullBar)
    }
    unsafe fn nonnullBar(self) -> Bar
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, nonnullBar)
    }
    unsafe fn nullableBar(self) -> Option<Bar>
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, nullableBar)
    }
}

This should also apply to parameters in functions. I've kept the nonnull functions because that's a very important use case that we need to preserve.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant