mozilla / mozilla/cbindgen

`assertion failed` when two generic enums share variant names and are monomorphized over the same concrete type

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

Nobody has claimed this yet.

Dominant language
Rust
Stars
3k
Forks
386
Avg merge
1h 43m
Merged PRs (30d)
1

Description

cbindgen panics during monomorphization if two distinct #[repr(C)] enums declare a data-bearing variant with the same name (e.g. both have an Ok(T) variant) and both get monomorphized over the same concrete type.

The payload struct that cbindgen synthesizes for each enum variant is named solely after the variant identifier, independent of the enclosing enum:

let path = Path::new(format!("{}_Body", variant.ident));

(src/bindgen/ir/enumeration.rs)

So EnumA<T>::Ok and EnumB<T>::Ok both produce a payload path Ok_Body, and instantiating both with the same T tries to register Ok_Body<T> twice, triggering the debug_assert!(!self.contains(&replacement_path)) in src/bindgen/monomorph.rs.

It seems cbindgen:prefix-with-name=true config also doesn't help because it applies later, and does not affect the path used during monomorph.rs

Minimial Repro

use std::os::raw::c_void;
#[repr(C)]
pub enum ResultA<T> {
    Ok(T),
    Err(*mut c_void),
}
// Same `Ok`/`Err` variant *names* as ResultA.
#[repr(C)]
pub enum ResultB<T> {
    Ok(T),
    Err(*mut c_void),
}
#[repr(C)]
pub struct Payload {
    pub x: i32,
}
// Force both enums to be monomorphized over the SAME type.
#[no_mangle]
pub extern "C" fn use_a(_a: ResultA<Payload>) {}
#[no_mangle]
pub extern "C" fn use_b(_b: ResultB<Payload>) {}

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 in src/bindgen/ir/enumeration.rs where variant payload paths are formed, then trace registration in src/bindgen/monomorph.rs, including the debug assertion. Run the minimal reproduction with ResultA and ResultB instantiated over Payload. Done means both enums can be monomorphized without the assertion failure and their payload types remain distinguishable.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.