rust-lang / rust-lang/rust-bindgen

bindgen Incompatibility with LLVM 21.1 C++ Template Metaprogramming

Open
#3,256 0 comments 1 reaction 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

ISSUE

bindgen fails to parse LLVM 21's libc++ template metaprogramming, specifically std::basic_string_view and std::invoke_result_t templates, generating invalid Rust code.

EXPECTED BEHAVIOR

bindgen should handle LLVM 21's C++ standard library templates gracefully, either by parsing them correctly or providing better fallback mechanisms.

STEPS TO REPRODUCE

Environment:

  • LLVM 21.1.0-rc1
  • bindgen 0.72.0
  • macOS 15.5 aarch64
  • Large C++ codebase (Firefox) with complex template usage

Minimal Reproduction Case:

// test.hpp
#include <string_view>
#include <type_traits>

template<typename F, typename... Args>
using invoke_result_test = std::invoke_result_t<F, Args...>;

class TestClass {
public:
    std::string_view get_view() const;
    template<typename Func>
    auto call_func(Func f) -> std::invoke_result_t<Func>;
};

bindgen Command:

bindgen test.hpp --output test.rs -- -std=c++17 -I/opt/llvm-21.1.0-rc1/include/c++/v1

ATTEMPTS TO RESOLVE

1. Basic String View Template Issues
Generated Invalid Rust:

error[E0412]: cannot find type `_CharT` in this scope
error[E0412]: cannot find type `_Traits` in this scope
error[E0109]: type arguments are not allowed on builtin type `u8`

Working Fix - Template Blocking:

.blocklist_type(".*basic_string_view.*")
.opaque_type(".*basic_string_view.*")
.blocklist_type("std::.*basic_string_view.*") 
.opaque_type("std::.*basic_string_view.*")
.blocklist_type("std::__1::basic_string_view.*")
.opaque_type("std::__1::basic_string_view.*")
2. invoke_result_t Template Issues

Generated Invalid Rust:

error[E0412]: cannot find type `invoke_result_t` in module `root::std::__1`
     --> structs.rs:51072:29
      |
51072 |             root::std::__1::invoke_result_t<ResolveFunction, ResolveValueT>;
      |                             ^^^^^^^^^^^^^^^ not found in `root::std::__1`

Attempted Fix (Partial Success):

.blocklist_type(".*__invoke_result_t.*")
.opaque_type(".*__invoke_result_t.*")
.blocklist_type(".*invoke_result_t.*")
.opaque_type(".*invoke_result_t.*")

Result: Some instances blocked, but template still leaks through in complex instantiations.

OUTCOME AND FINDINGS

Root Cause Analysis

  1. Template Parameter Extraction: bindgen attempts to extract template parameters (_CharT, _Traits, _Args) but fails to resolve them in LLVM 21's more complex template definitions
  2. SFINAE Handling: LLVM 21 uses more sophisticated SFINAE patterns that bindgen's template parser cannot handle
  3. Namespace Resolution: Complex nested template instantiations in std::__1 namespace are not properly resolved

LLVM 21 Specific Changes
LLVM 21's libc++ appears to use more aggressive template metaprogramming:

// LLVM 21 style - more complex SFINAE
template<class _Fn, class... _Args>
using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;

// Earlier versions - simpler patterns  
template<class F, class... Args>
using invoke_result_t = typename invoke_result<F, Args...>::type;

Workaround Effectiveness

  • blocklist_type + opaque_type: Effective for simple cases
  • Regex patterns: Inconsistent - some template instantiations still leak through
  • Template recursion: Deep template hierarchies still cause issues

REQUESTED ACTION

Short Term

  1. Improve Template Blocking: Make blocklist_type patterns more aggressive at catching complex template instantiations
  2. Better Error Messages: When template parsing fails, provide clearer guidance on blocking problematic types
  3. Template Fallback: When complex templates can't be parsed, fall back to opaque types automatically

Long Term

  1. C++17/20 Template Support: Enhance parser to handle modern C++ template metaprogramming patterns
  2. SFINAE Recognition: Detect and gracefully handle SFINAE patterns that will never generate valid Rust
  3. Standard Library Profiles: Pre-configured blocklists for known problematic stdlib template patterns

Specific Technical Improvements

  1. Template Parameter Resolution: Fix handling of unresolved template parameters in complex instantiations
  2. Namespace Qualification: Improve resolution of deeply nested template types in std::__1
  3. Recursive Template Blocking: When a template is blocked, also block all its dependent instantiations

This affects any large C++ codebase attempting to use LLVM 21 with bindgen.

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 running the bindgen command against the provided test.hpp with LLVM 21.1 and inspecting the invalid output in test.rs and the reported structs.rs errors. Read the template parsing, namespace resolution, and blocklist handling paths to determine which behavior is reproducible. Done would require a defined fix for the reported template failures, with tests showing that problematic instantiations no longer generate invalid Rust.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, rust
Domain
compilers, tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.