rust-lang / rust-lang/rust-bindgen

Objective-c categories aren't included in inheritance traits and impl blocks

Open
#1,779 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

Objective-c categories are a way of extending a given objective-c class. It almost feels like categories are used to organize various sections of their codebase. As a result, there are a lot of categories in the apple frameworks.

In #1750 I added better inheritance support for the binding generation but didn't add the impl blocks for the traits generated from the Objective-c categories.

It's unclear to me how to best implement this because a given class has no reference to the classes it implements. The only reference to the classes are from the categories to the classes they extend.

Input C/C++ Header
// bindgen-flags: --objc-extern-crate -- -x objective-c
// bindgen-osx-only

@interface Foo
-(void)method;
@end

@interface Foo (BarCategory)
-(void)categoryMethod;
@end

@interface Bar: Foo
@end
Bindgen Invocation
$ bindgen input.h --objc-extern-crate -- -x objective-c
Actual Results
/* automatically generated by rust-bindgen */

#![allow(
    dead_code,
    non_snake_case,
    non_camel_case_types,
    non_upper_case_globals
)]
#![cfg(target_os = "macos")]

#[macro_use]
extern crate objc;
#[allow(non_camel_case_types)]
pub type id = *mut objc::runtime::Object;
#[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 method(self)
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, method)
    }
}
impl Foo_BarCategory for Foo {}
pub trait Foo_BarCategory: Sized + std::ops::Deref {
    unsafe fn categoryMethod(self)
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, categoryMethod)
    }
}
#[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 IFoo for Bar {}
impl IBar for Bar {}
pub trait IBar: Sized + std::ops::Deref {}
Expected Results

impl Foo_BarCategory for Bar {} is missing and should be something like the following:

...
impl IFoo for Bar {}
impl IBar for Bar {}
impl Foo_BarCategory for Bar {}
pub trait IBar: Sized + std::ops::Deref {}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Objective-C inheritance and category binding-generation paths described in the issue, using the supplied header and bindgen invocation as the reproduction case. Verify that a subclass receives the category trait implementation, with impl Foo_BarCategory for Bar {} appearing in the generated Rust output alongside the existing trait implementations.

Written by the indexing model from the issue text.

Assessment

Tech stack
objective-c, rust
Domain
tooling
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.