From 695310dac70c27f84eb6c724f2c6f4eb5b1858e5 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 13:51:28 +0100 Subject: [PATCH 1/4] Fix list initializer for union --- cpp2rust/converter/converter.cpp | 8 ++++++++ cpp2rust/converter/models/converter_refcount.cpp | 15 +++++++++++++++ tests/unit/union_basic.cpp | 5 +++++ 3 files changed, 28 insertions(+) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index b63c7fcb3..d7d28dc14 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -3567,6 +3567,14 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) { StrCat(GetUnsafeTypeAsString(qual_type)); PushBrace brace(*this); + if (record->isUnion()) { + auto *field = expr->getInitializedFieldInUnion(); + assert(field && expr->getNumInits() == 1); + StrCat(GetNamedDeclAsString(field), token::kColon); + ConvertFieldInit(field, expr->getInit(0)); + SetFreshType(qual_type); + return false; + } int i = 0; for (const auto *field : record->fields()) { StrCat(GetNamedDeclAsString(field), token::kColon); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 9a5f74873..f40de16d1 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1905,6 +1905,21 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { return false; } + if (record->isUnion()) { + auto *field = expr->getInitializedFieldInUnion(); + assert(field && expr->getNumInits() == 1); + PushConversionKind push(*this, ConversionKind::Unboxed); + auto name = GetUnsafeTypeAsString(qual_type); + StrCat(std::format("{{ let __u: Value<{}> = Rc::new(RefCell::new({}));", + name, GetDefaultAsString(qual_type))); + StrCat(std::format("{}::{}(__u.as_pointer()).write(", name, + GetNamedDeclAsString(field))); + ConvertVarInit(field->getType(), expr->getInit(0)); + StrCat("); Rc::try_unwrap(__u).ok().unwrap().into_inner() }"); + computed_expr_type_ = ComputedExprType::FreshValue; + return false; + } + StrCat(GetUnsafeTypeAsString(qual_type)); { PushBrace brace(*this); diff --git a/tests/unit/union_basic.cpp b/tests/unit/union_basic.cpp index c73c7673b..0c416a37c 100644 --- a/tests/unit/union_basic.cpp +++ b/tests/unit/union_basic.cpp @@ -33,5 +33,10 @@ int main(void) { assert(*pf == 1.0f); assert(buf[3] == 0x3F); + union basic braced{5}; + assert(braced.i == 5); + union basic copied = {7}; + assert(copied.i == 7); + return 0; } From 4f6a322618113cf46827305ad11fd0e306dc6ac8 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 9 Oct 2026 19:09:50 +0100 Subject: [PATCH 2/4] Update tests --- tests/unit/out/refcount/union_basic.rs | 12 ++++++++++++ tests/unit/out/unsafe/union_basic.rs | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/tests/unit/out/refcount/union_basic.rs b/tests/unit/out/refcount/union_basic.rs index 6ccc5aaa7..9a1b7ed69 100644 --- a/tests/unit/out/refcount/union_basic.rs +++ b/tests/unit/out/refcount/union_basic.rs @@ -71,6 +71,18 @@ fn main_0() -> i32 { assert!(((basic::i(ru.clone()).read()) == 1065353216)); assert!(((pf.read()) == 1_f32)); assert!((((*buf.borrow())[(3) as usize] as i32) == 63)); + let braced: Value = Rc::new(RefCell::new({ + let __u: Value = Rc::new(RefCell::new(::default())); + basic::i(__u.as_pointer()).write(5); + Rc::try_unwrap(__u).ok().unwrap().into_inner() + })); + assert!(((basic::i(braced.as_pointer()).read()) == 5)); + let copied: Value = Rc::new(RefCell::new({ + let __u: Value = Rc::new(RefCell::new(::default())); + basic::i(__u.as_pointer()).write(7); + Rc::try_unwrap(__u).ok().unwrap().into_inner() + })); + assert!(((basic::i(copied.as_pointer()).read()) == 7)); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/union_basic.rs b/tests/unit/out/unsafe/union_basic.rs index 870ea8b18..3c438da57 100644 --- a/tests/unit/out/unsafe/union_basic.rs +++ b/tests/unit/out/unsafe/union_basic.rs @@ -58,6 +58,10 @@ unsafe fn main_0() -> i32 { assert!((((*ru).i) == (1065353216))); assert!(((*pf) == (1_f32))); assert!(((buf[(3) as usize] as i32) == (63))); + let mut braced: basic = basic { i: 5 }; + assert!(((braced.i) == (5))); + let mut copied: basic = basic { i: 7 }; + assert!(((copied.i) == (7))); return 0; } pub unsafe fn __cpp2rust_init_globals() {} From 0819f61e4f7c0811cdcd423a6b66907bc9267d9d Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 12 Oct 2026 09:26:10 +0100 Subject: [PATCH 3/4] Update tests --- tests/unit/out/refcount/union_basic.rs | 12 ++++++++++++ tests/unit/out/unsafe/union_basic.rs | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/tests/unit/out/refcount/union_basic.rs b/tests/unit/out/refcount/union_basic.rs index 5c5ed59d7..fd14d5907 100644 --- a/tests/unit/out/refcount/union_basic.rs +++ b/tests/unit/out/refcount/union_basic.rs @@ -93,6 +93,18 @@ fn main_0() -> i32 { assert!(((basic::i(ru.clone()).read()) == 1065353216)); assert!(((pf.read()) == 1_f32)); assert!((((*buf.borrow())[(3) as usize] as i32) == 63)); + let braced: Value = Rc::new(RefCell::new({ + let __u: Value = Rc::new(RefCell::new(::default())); + basic::i(__u.as_pointer()).write(5); + Rc::try_unwrap(__u).ok().unwrap().into_inner() + })); + assert!(((basic::i(braced.as_pointer()).read()) == 5)); + let copied: Value = Rc::new(RefCell::new({ + let __u: Value = Rc::new(RefCell::new(::default())); + basic::i(__u.as_pointer()).write(7); + Rc::try_unwrap(__u).ok().unwrap().into_inner() + })); + assert!(((basic::i(copied.as_pointer()).read()) == 7)); let us: Value = Rc::new(RefCell::new(::default())); underscores::__(us.as_pointer()).write(5); assert!(((underscores::__(us.as_pointer()).read()) == 5)); diff --git a/tests/unit/out/unsafe/union_basic.rs b/tests/unit/out/unsafe/union_basic.rs index eb1de9e12..8b9b29413 100644 --- a/tests/unit/out/unsafe/union_basic.rs +++ b/tests/unit/out/unsafe/union_basic.rs @@ -69,6 +69,10 @@ unsafe fn main_0() -> i32 { assert!((((*ru).i) == (1065353216))); assert!(((*pf) == (1_f32))); assert!(((buf[(3) as usize] as i32) == (63))); + let mut braced: basic = basic { i: 5 }; + assert!(((braced.i) == (5))); + let mut copied: basic = basic { i: 7 }; + assert!(((copied.i) == (7))); let mut us: underscores = ::default(); us.__ = 5; assert!(((us.__) == (5))); From a971cbcb21a4563b807403b56ec6bddd09ee5011 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 12 Oct 2026 16:44:28 +0100 Subject: [PATCH 4/4] Update tesst --- tests/unit/out/refcount/union_basic.rs | 12 ++++++++++++ tests/unit/out/unsafe/union_basic.rs | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/tests/unit/out/refcount/union_basic.rs b/tests/unit/out/refcount/union_basic.rs index 4d60b4896..b35da820c 100644 --- a/tests/unit/out/refcount/union_basic.rs +++ b/tests/unit/out/refcount/union_basic.rs @@ -93,6 +93,18 @@ fn main_0() -> i32 { assert!(((basic::i(ru.clone()).read()) == 1065353216)); assert!(((pf.read()) == 1_f32)); assert!((((*buf.borrow())[(3) as usize] as i32) == 63)); + let braced: Value = Rc::new(RefCell::new({ + let __u: Value = Rc::new(RefCell::new(::default())); + basic::i(__u.as_pointer()).write(5); + Rc::try_unwrap(__u).ok().unwrap().into_inner() + })); + assert!(((basic::i(braced.as_pointer()).read()) == 5)); + let copied: Value = Rc::new(RefCell::new({ + let __u: Value = Rc::new(RefCell::new(::default())); + basic::i(__u.as_pointer()).write(7); + Rc::try_unwrap(__u).ok().unwrap().into_inner() + })); + assert!(((basic::i(copied.as_pointer()).read()) == 7)); { let anon_0: Value = Rc::new(RefCell::new(::default())); anon_0::ai(anon_0.as_pointer()).write(11); diff --git a/tests/unit/out/unsafe/union_basic.rs b/tests/unit/out/unsafe/union_basic.rs index 999cd945e..91ddf5a39 100644 --- a/tests/unit/out/unsafe/union_basic.rs +++ b/tests/unit/out/unsafe/union_basic.rs @@ -69,6 +69,10 @@ unsafe fn main_0() -> i32 { assert!((((*ru).i) == (1065353216))); assert!(((*pf) == (1_f32))); assert!(((buf[(3) as usize] as i32) == (63))); + let mut braced: basic = basic { i: 5 }; + assert!(((braced.i) == (5))); + let mut copied: basic = basic { i: 7 }; + assert!(((copied.i) == (7))); { let mut anon_0: anon_0 = ::default(); anon_0.ai = 11;