ObjC ARC `__weak` struct fields are passed by value (`Copy`) instead of the hidden-pointer ABI

Open
#3,463 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

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

Research direction

Start with input.h and reproduce the bindgen invocation using Objective-C ARC on aarch64-apple-darwin. Compare the generated W definition and takeW declaration with Clang's calling convention for a struct containing __weak id. Done means bindgen no longer emits an incorrect Copy by-value signature, either matching the hidden-pointer ABI or refusing that binding.

Written by the indexing model from the issue text.

Description

Input C/C++ Header
typedef struct objc_object *id;

typedef struct {
    __weak id w;
    int t;
} W;

int takeW(W s, int z);
int takeWp(id p, int t);
id box7(void);
Bindgen Invocation
$ bindgen input.h --no-rustfmt-bindings -- -x objective-c -fobjc-arc
Actual Results

bindgen emits a Copy by-value struct. Layout tests compile (size_of::<W>() == 16).

#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct W {
    pub w: id,
    pub t: ::std::os::raw::c_int,
}

unsafe extern "C" {
    pub fn takeW(s: W, z: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
    pub fn takeWp(p: id, t: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
}

An __weak field makes the record nontrivial for calls under ARC. Clang passes takeW indirectly (objc_copyWeak / hidden pointer). rustc passes [2 x i64] in registers.

On Darwin aarch64, s.t = 10, z = 1:

C  takeW(s, 1) = 11    takeWp(o, 10) = 11
Rust takeW(s, 1) = 10    takeWp(o, 10) = 11

The thin __weak id parameter matches. Only the by-value struct disagrees.

This is not #778 (C++ Itanium user-destructor “non-trivial for the purposes of calls”). It is a C struct with an ObjC ARC ownership qualifier. bindgen has no __weak / objc_ownership handling.

Expected Results

A record with an __weak field should not be passed as a Copy by-value argument. Clang’s calling convention for that type is a hidden pointer; the generated signature should match that (or bindgen should refuse to emit a by-value Copy binding).

Environment
bindgen current main: 77cbc72
bindgen:              0.73.1
clang:                Apple clang 21.0.0
rustc:                1.97.1
target:               aarch64-apple-darwin
Dominant language
Rust
Stars
5.3k
Forks
846
Avg merge
2d 6h
Merged PRs (30d)
11

Getting set up

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.

More from rust-lang/rust-bindgen

All issues in rust-lang/rust-bindgen

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.