-
Notifications
You must be signed in to change notification settings - Fork 762
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
- 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 - SFINAE Handling: LLVM 21 uses more sophisticated SFINAE patterns that bindgen's template parser cannot handle
- 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
- Improve Template Blocking: Make blocklist_type patterns more aggressive at catching complex template instantiations
- Better Error Messages: When template parsing fails, provide clearer guidance on blocking problematic types
- Template Fallback: When complex templates can't be parsed, fall back to opaque types automatically
Long Term
- C++17/20 Template Support: Enhance parser to handle modern C++ template metaprogramming patterns
- SFINAE Recognition: Detect and gracefully handle SFINAE patterns that will never generate valid Rust
- Standard Library Profiles: Pre-configured blocklists for known problematic stdlib template patterns
Specific Technical Improvements
- Template Parameter Resolution: Fix handling of unresolved template parameters in complex instantiations
- Namespace Qualification: Improve resolution of deeply nested template types in std::__1
- 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.