rust-lang / rust-lang/rust-bindgen

[Objc] Objective-c category names are not unique and can cause duplicate names

Open
#1,889 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-Obj-C bug
Dominant language
Rust
Stars
5.3k
Forks
829
Avg merge
1d 1h
Merged PRs (30d)
15

Description

Found this today when using bindgen on AppKit. Looks like there's an NSImage category (with no name) created twice.

My example below uses nameless categories like AppKit does but you can also just give them names and it's the same bug. I'm pretty sure that this is bad practice from apple but it's still part of the objective-c grammar so I figure I'd write this ticket for the next person. It's unclear how common this issue is so it's possible that it's not worth fixing.

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

@interface NSImage
@end
@interface NSImage ()
@end
@interface NSImage ()
- (int*)foo;
@end
Bindgen Invocation
$ bindgen input.h input.h -- -x objective-c
Actual Results
/* automatically generated by rust-bindgen 0.55.1 */

use objc;
#[allow(non_camel_case_types)]
pub type id = *mut objc::runtime::Object;
#[repr(transparent)]
#[derive(Clone, Copy)]
pub struct NSImage(pub id);
impl std::ops::Deref for NSImage {
    type Target = objc::runtime::Object;
    fn deref(&self) -> &Self::Target {
        unsafe { &*self.0 }
    }
}
unsafe impl objc::Message for NSImage {}
impl NSImage {
    pub fn alloc() -> Self {
        Self(unsafe { msg_send!(objc::class!(NSImage), alloc) })
    }
}
impl INSImage for NSImage {}
pub trait INSImage: Sized + std::ops::Deref {}
impl NSImage_ for NSImage {}
pub trait NSImage_: Sized + std::ops::Deref {}
impl NSImage_ for NSImage {}
pub trait NSImage_: Sized + std::ops::Deref {
    unsafe fn foo(self) -> *mut ::std::os::raw::c_int
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, foo)
    }
}
Expected Results

I'm not sure what to add but a suffix at the end like NSImage_2 would make it unique.

impl NSImage_ for NSImage {}
pub trait NSImage_: Sized + std::ops::Deref {}
impl NSImage_2 for NSImage {}
pub trait NSImage_2: Sized + std::ops::Deref {
    unsafe fn foo(self) -> *mut ::std::os::raw::c_int
    where
        <Self as std::ops::Deref>::Target: objc::Message + Sized,
    {
        msg_send!(self, foo)
    }
}

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 by reproducing the issue with the provided input.h and bindgen invocation, then trace Objective-C category handling and generated Rust trait naming. Done means repeated or named categories produce unique generated names, with a regression test covering the duplicate-category case.

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
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.