rust-lang / rust-lang/rust-bindgen
Add Option return types to Objective-c for nullability attributes
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 5.3k
- Forks
- 829
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 15
Description
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.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the issue with the supplied input.h and bindgen invocation, then trace how Objective-C method and property nullability reaches the generated Rust signatures. Done means nullable object returns and parameters use Option while nonnull declarations remain unchanged, including the shown methods and properties.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- objective-c, rust
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100