diff --git a/engine/src/conversion/analysis/name_check.rs b/engine/src/conversion/analysis/name_check.rs index 3d1c044b8..48a54459c 100644 --- a/engine/src/conversion/analysis/name_check.rs +++ b/engine/src/conversion/analysis/name_check.rs @@ -22,7 +22,7 @@ use crate::{ error_reporter::convert_item_apis, ConvertError, }, - types::{validate_ident_ok_for_rust, QualifiedName}, + types::{validate_ident_ok_for_cxx, QualifiedName}, }; use super::fun::FnAnalysis; @@ -37,15 +37,11 @@ pub(crate) fn check_names(apis: Vec>) -> Vec> { | ApiDetail::Const { .. } | ApiDetail::Enum { .. } | ApiDetail::Struct { .. } => { - let cxx_name = api - .cpp_name - .as_ref() - .map(|s| - QualifiedName::new_from_cpp_name(&s) - ) - .unwrap_or_else(|| api.name.clone()); - for seg in cxx_name.segment_iter() { - validate_ident_ok_for_rust(&seg)?; + validate_all_segments_ok_for_cxx(api.name.segment_iter())?; + if let Some(ref cpp_name) = api.cpp_name { + // The C++ name might itself be outer_type::inner_type and thus may + // have multiple segments. + validate_all_segments_ok_for_cxx(QualifiedName::new_from_cpp_name(cpp_name).segment_iter())?; } Ok(Some(api)) } @@ -85,6 +81,15 @@ pub(crate) fn check_names(apis: Vec>) -> Vec> { results } +fn validate_all_segments_ok_for_cxx( + items: impl Iterator, +) -> Result<(), ConvertError> { + for seg in items { + validate_ident_ok_for_cxx(&seg)?; + } + Ok(()) +} + fn cxxbridge_name(api: &Api) -> Option { match api.detail { ApiDetail::Function { ref analysis, .. } => Some(analysis.cxxbridge_name.clone()), diff --git a/engine/src/integration_tests.rs b/engine/src/integration_tests.rs index f4e3fe19f..93af7da33 100644 --- a/engine/src/integration_tests.rs +++ b/engine/src/integration_tests.rs @@ -5213,6 +5213,23 @@ fn test_closure() { run_test("", hdr, rs, &["get_a"], &[]); } +#[test] +fn test_underscored_namespace_for_inner_type() { + let hdr = indoc! {" + namespace __foo { + struct daft { + struct bob { + int a; + }; + int a; + }; + } + inline void bar(__foo::daft::bob) {} + "}; + let rs = quote! {}; + run_test("", hdr, rs, &["bar"], &[]); +} + #[test] fn test_blocklist_not_overly_broad() { // This is a regression test. We used to block anything that starts with "rust" or "std",