Skip to content

Strip r# prefix from raw identifiers in generated C++ names - #1749

Open
HarnageaGabriel wants to merge 1 commit into
dtolnay:masterfrom
HarnageaGabriel:fix-raw-ident-cpp-codegen
Open

Strip r# prefix from raw identifiers in generated C++ names#1749
HarnageaGabriel wants to merge 1 commit into
dtolnay:masterfrom
HarnageaGabriel:fix-raw-ident-cpp-codegen

Conversation

@HarnageaGabriel

Copy link
Copy Markdown

Summary

Fixes #1324.

A raw identifier used in an extern "C++" block purely to dodge a Rust
keyword (e.g. pub fn highlight(r#type: i32);) was being emitted verbatim
into the generated C++, including the r# prefix:

void ffi$cxxbridge1$highlight(::std::int32_t r#type) noexcept { ... }

which is not valid C++.

Root cause

ForeignName::parse (syntax/names.rs) is the single place that turns a
Rust identifier into its C++-facing name — used both for the implicit
default name and for explicit #[cxx_name = ...] attributes — but it
never stripped the r# marker before storing the name.

Fix

Strip a leading r# in ForeignName::parse, mirroring the existing
precedent in QualifiedName::parse_unquoted (syntax/qualified.rs), which
already does this for raw identifiers in namespace segments.

This intentionally stays narrowly scoped to the issue: it doesn't attempt
to detect or rename identifiers that, after stripping r#, would collide
with a C++ reserved keyword (e.g. class, template) — the crate has no
C++ keyword list today, and adding one is out of scope for this fix.

Test plan

  • Added test_raw_identifier_param in tests/cxx_gen.rs, asserting
    the generated header/implementation contain no r# and the expected
    C++ signature uses the bare identifier.
  • cargo test --test cxx_gen passes (4/4).
  • cargo build succeeds for the whole workspace.

🤖 Generated with Claude Code

extern "C++" parameters/fields named with a raw identifier (e.g.
r#type, used only to dodge a Rust keyword) were emitted verbatim
into generated C++, producing invalid code like
`void foo(::std::int32_t r#type) noexcept`.

ForeignName::parse is the single place that turns a Rust identifier
into its C++-facing name, both for the implicit default name and for
explicit #[cxx_name = ...] attributes, so strip the r# prefix there.
This mirrors the existing precedent in QualifiedName::parse_unquoted
(syntax/qualified.rs) for namespace segments.

Fixes dtolnay#1324
@HarnageaGabriel
HarnageaGabriel force-pushed the fix-raw-ident-cpp-codegen branch from 4723722 to 7d9b121 Compare August 19, 2026 19:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Raw identifiers in methods in extern "C++" block leads to wrong C++ code generation

1 participant