Skip to content

Attempt to implement support for self-referential union types - #3419

Open
erickt wants to merge 1 commit into
rust-lang:mainfrom
erickt:union2
Open

Attempt to implement support for self-referential union types#3419
erickt wants to merge 1 commit into
rust-lang:mainfrom
erickt:union2

Conversation

@erickt

@erickt erickt commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

In llvm/llvm-project#185449, LLVM's libc++ changed a header to use a recursive self-referential type, which looks approximately like:

template <class A0, class... As> union RUnion { A0 arg; RUnion<As...> u; };
template <class A> union RUnion<A> { A arg; };
struct Wrap { RUnion<int, float> u; };

This code caused bindgen to panic. The problem seems to be that bindgen can't handle the recursive self-referential union. Digging into the code, it seems that when this type is being parsed, with_loaned_item removes the type from the context. Later on, when parsing the CompKind::Union, CompInfo::layout would call resolve_type on an item that was loaned out, so it panics. This bug was filed in #3397.

I've attempted to fix this bug with the help of Gemini agent, and it seems that we might be able to swap out resolve_type with safe_resolve_type in a few locations to get it to stop erroring out. This seems to make sense as best as I understand this situation, although there may be a chance that returning None in these callsites might be incorrect. But I couldn't find a counter example that shows incorrect code. As a safeguard, this also tracks which items we have loaned out, and makes sure that safe_resolve_type will panic if these types weren't loaned out.

Fixes #3397

@erickt

erickt commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

r? @emilio

@erickt
erickt force-pushed the union2 branch 8 times, most recently from cff08ee to d21afc5 Compare August 4, 2026 22:22
In llvm/llvm-project#185449, LLVM's libc++ changed a header to use a
recursive self-referential type, which looks approximately like:

```
template <class A0, class... As> union RUnion { A0 arg; RUnion<As...> u; };
template <class A> union RUnion<A> { A arg; };
struct Wrap { RUnion<int, float> u; };
```

This code caused bindgen to panic. The problem seems to be that bindgen
can't handle the recursive self-referential union. Digging into the
code, it seems that when this type is being parsed, `with_loaned_item`
removes the type from the context. Later on, when parsing the
CompKind::Union, CompInfo::layout would call resolve_type on an item
that was loaned out, so it panics. This bug was filed in rust-lang#3397.

This patch avoids that by first keeping track of which items we have
loaed out with `with_loaned_item`, then changing `safe_resolve_type` to
panic if we don't have an entry for that type, or it has been loaned
out. Then we've updated the call sites to use it.

This also adds LLVM-21 tests, since clang generates different code than
LLVM-20.

Test: cargo test -p bindgen-tests

TAG=agy
CONV=619bdf72-4d2d-494f-8cb0-f61a6db9674c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bindgen panicked with message "Not an item: ItemId(...)" when parsing recursive union templates (breaks recent LLVM libc++ std::aligned_union)

3 participants