From a9453262e825dbf3aba0fd6b6e46daa728898185 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sun, 27 Sep 2026 14:33:05 +0100 Subject: [PATCH 1/3] Fix collisions between user records and libcc2rs names --- cpp2rust/converter/mapper.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cpp2rust/converter/mapper.cpp b/cpp2rust/converter/mapper.cpp index 0464976ce..4e08912b2 100644 --- a/cpp2rust/converter/mapper.cpp +++ b/cpp2rust/converter/mapper.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -737,6 +738,16 @@ std::string ToRustName(std::string name) { c = '_'; } } + // Ptr -> Ptr_ so it doesn't shadow libcc2rs::Ptr; Ptr_ -> Ptr__ so it doesn't + // collide with the renamed Ptr, etc + for (std::string_view runtime_name : {"Ptr", "Value"}) { + if (name.starts_with(runtime_name) && + std::ranges::all_of(std::string_view(name).substr(runtime_name.size()), + [](char c) { return c == '_'; })) { + name += '_'; + break; + } + } return name; } From 40a58049e59b1b41d70d8593995ed9ca5826c162 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Tue, 29 Sep 2026 08:10:38 +0100 Subject: [PATCH 2/3] Avoid collision between user-defined record and libcc2rs --- cpp2rust/converter/mapper.cpp | 3 +- tests/unit/out/refcount/struct_ctor.rs | 84 ++++++++++++++++++++++++++ tests/unit/out/unsafe/struct_ctor.rs | 34 +++++++++++ tests/unit/struct_ctor.cpp | 17 ++++++ 4 files changed, 136 insertions(+), 2 deletions(-) diff --git a/cpp2rust/converter/mapper.cpp b/cpp2rust/converter/mapper.cpp index 4e08912b2..387d8c1ce 100644 --- a/cpp2rust/converter/mapper.cpp +++ b/cpp2rust/converter/mapper.cpp @@ -738,8 +738,7 @@ std::string ToRustName(std::string name) { c = '_'; } } - // Ptr -> Ptr_ so it doesn't shadow libcc2rs::Ptr; Ptr_ -> Ptr__ so it doesn't - // collide with the renamed Ptr, etc + for (std::string_view runtime_name : {"Ptr", "Value"}) { if (name.starts_with(runtime_name) && std::ranges::all_of(std::string_view(name).substr(runtime_name.size()), diff --git a/tests/unit/out/refcount/struct_ctor.rs b/tests/unit/out/refcount/struct_ctor.rs index 4df61ad79..6384da7b4 100644 --- a/tests/unit/out/refcount/struct_ctor.rs +++ b/tests/unit/out/refcount/struct_ctor.rs @@ -53,6 +53,87 @@ impl ByteRepr for StructWithCtor { pub fn foo_0(x: Ptr) -> Ptr { return (x).clone(); } +#[derive(Default)] +pub struct Value_ { + pub v: Value, +} +impl Value_ { + pub fn new(u: i32) -> Self { + let u: Value = Rc::new(RefCell::new(u)); + let __this: Value = Rc::new(RefCell::new(Self { + v: Rc::new(RefCell::new((*u.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl Clone for Value_ { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + v: Rc::new(RefCell::new((*self.v.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for Value_ { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.v.borrow()).to_bytes(&mut buf[0..4]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + v: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + } + } +} +#[derive()] +pub struct Ptr_ { + pub v1: Value, + pub v2: Value, +} +impl Ptr_ { + pub fn new() -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + v1: Rc::new(RefCell::new(Value_::new({ 11 }))), + v2: Rc::new(RefCell::new(Value_::new({ 22 }))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl Clone for Ptr_ { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + v1: Rc::new(RefCell::new((*self.v1.borrow()).clone())), + v2: Rc::new(RefCell::new((*self.v2.borrow()).clone())), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl Default for Ptr_ { + fn default() -> Self { + { Ptr_::new() } + } +} +impl ByteRepr for Ptr_ { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.v1.borrow()).to_bytes(&mut buf[0..4]); + (*self.v2.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + v1: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + v2: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -66,6 +147,9 @@ fn main_0() -> i32 { && ((({ StructWithCtorImpl::x1(&struct_with_ctor.as_pointer(),) }).read()) == 2)) && ((({ StructWithCtorImpl::x2(&struct_with_ctor.as_pointer(),) }).read()) == 1) ); + let p: Value = Rc::new(RefCell::new(Ptr_::new())); + assert!(((*(*(*p.borrow()).v1.borrow()).v.borrow()) == 11)); + assert!(((*(*(*p.borrow()).v2.borrow()).v.borrow()) == 22)); return 0; } pub trait StructWithCtorImpl { diff --git a/tests/unit/out/unsafe/struct_ctor.rs b/tests/unit/out/unsafe/struct_ctor.rs index 568cddfd3..bbaed8a07 100644 --- a/tests/unit/out/unsafe/struct_ctor.rs +++ b/tests/unit/out/unsafe/struct_ctor.rs @@ -29,6 +29,37 @@ impl StructWithCtor { pub unsafe fn foo_0(x: *mut i32) -> *mut i32 { return x; } +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct Value_ { + pub v: i32, +} +impl Value_ { + pub unsafe fn new(mut u: i32) -> Self { + let mut this = Self { v: u }; + this + } +} +#[repr(C)] +#[derive(Copy, Clone)] +pub struct Ptr_ { + pub v1: Value_, + pub v2: Value_, +} +impl Ptr_ { + pub unsafe fn new() -> Self { + let mut this = Self { + v1: Value_::new({ 11 }), + v2: Value_::new({ 22 }), + }; + this + } +} +impl Default for Ptr_ { + fn default() -> Self { + unsafe { Ptr_::new() } + } +} pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -43,6 +74,9 @@ unsafe fn main_0() -> i32 { && ((*(unsafe { StructWithCtor::x1(&struct_with_ctor,) })) == (2))) && ((*(unsafe { StructWithCtor::x2(&struct_with_ctor,) })) == (1)) ); + let mut p: Ptr_ = Ptr_::new(); + assert!(((p.v1.v) == (11))); + assert!(((p.v2.v) == (22))); return 0; } pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/struct_ctor.cpp b/tests/unit/struct_ctor.cpp index 9afd5d997..cbb5ad922 100644 --- a/tests/unit/struct_ctor.cpp +++ b/tests/unit/struct_ctor.cpp @@ -13,10 +13,27 @@ struct StructWithCtor { const int &x2() const { return x2_; } }; int &foo(int &x) { return x; } + +struct Value { + int v; + Value(int u) : v(u) {} +}; + +struct Ptr { + Value v1; + Value v2; + + Ptr() : v1(11), v2(22) {} +}; + int main() { StructWithCtor struct_with_ctor(1, 2); int x = 3; assert(foo(x) == 3 && struct_with_ctor.x1() == 2 && struct_with_ctor.x2() == 1); + + auto p = Ptr(); + assert(p.v1.v == 11); + assert(p.v2.v == 22); return 0; } From bce3b1ad7c60868ddbe8e2392894e5a5fb7a1178 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Tue, 29 Sep 2026 08:14:18 +0100 Subject: [PATCH 3/3] Simplify string condition --- cpp2rust/converter/mapper.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/cpp2rust/converter/mapper.cpp b/cpp2rust/converter/mapper.cpp index 387d8c1ce..7cf96bcc9 100644 --- a/cpp2rust/converter/mapper.cpp +++ b/cpp2rust/converter/mapper.cpp @@ -739,13 +739,10 @@ std::string ToRustName(std::string name) { } } - for (std::string_view runtime_name : {"Ptr", "Value"}) { - if (name.starts_with(runtime_name) && - std::ranges::all_of(std::string_view(name).substr(runtime_name.size()), - [](char c) { return c == '_'; })) { - name += '_'; - break; - } + std::string_view stem(name); + stem = stem.substr(0, stem.find_last_not_of('_') + 1); + if (stem == "Ptr" || stem == "Value") { + name += '_'; } return name; }