From 96ac6c949ae75714b54021c30a039518d90196ee Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 09:57:16 +0100 Subject: [PATCH 01/21] Remove normalizeTranslationRule --- cpp2rust/converter/printer.cpp | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/cpp2rust/converter/printer.cpp b/cpp2rust/converter/printer.cpp index a4d2874c4..384aef9b3 100644 --- a/cpp2rust/converter/printer.cpp +++ b/cpp2rust/converter/printer.cpp @@ -8,10 +8,8 @@ #include #include -#include #include #include -#include #include #include @@ -78,24 +76,6 @@ clang::QualType normalizeQualType(clang::ASTContext &ctx, ctx); } -std::string normalizeTranslationRule(std::string rule) { - // Detach pointer from double reference. Useful for matching translation - // rules. - ReplaceAll(rule, "*&&", "* &&"); - - static const std::array, 1> - normalization_rules{{ - // Ignore constant template parameters, i.e. replace them with _. - {std::regex(R"(\b\d+\b)"), "_"}, - }}; - - for (const auto &r : normalization_rules) { - rule = std::regex_replace(rule, r.first, r.second); - } - - return rule; -} - } // namespace std::string ToRustName(std::string name) { @@ -171,7 +151,7 @@ std::string ToString(clang::ASTContext &ctx, clang::QualType qual_type, std::string out; llvm::raw_string_ostream os(out); ctx.getPointerType(pointee).print(os, getPrintPolicy(ctx)); - return normalizeTranslationRule(std::move(out)); + return out; } } @@ -200,7 +180,7 @@ std::string ToString(clang::ASTContext &ctx, clang::QualType qual_type, std::string type; llvm::raw_string_ostream os(type); normalizeQualType(ctx, qual_type).print(os, getPrintPolicy(ctx)); - return normalizeTranslationRule(std::move(type)); + return type; } std::string ToString(clang::ASTContext &ctx, const clang::NamedDecl *decl) { @@ -237,7 +217,7 @@ std::string ToString(clang::ASTContext &ctx, const clang::NamedDecl *decl) { if (!func_decl) { decl->printQualifiedName(os, getPrintPolicy(ctx)); - return normalizeTranslationRule(std::move(out)); + return out; } os << ToString(ctx, func_decl->getReturnType()) << ' '; @@ -324,7 +304,7 @@ std::string ToString(clang::ASTContext &ctx, const clang::NamedDecl *decl) { } } - return normalizeTranslationRule(std::move(out)); + return out; } std::string ToString(clang::ASTContext &ctx, const clang::Expr *expr) { From 57c7aeb7778f5603966e0d1b51c78a1efb5f17fb Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 09:59:28 +0100 Subject: [PATCH 02/21] Replace type bindings with tempalte argument bindings --- cpp2rust/converter/converter.cpp | 22 ++++++++++++++++++++++ cpp2rust/converter/converter.h | 2 ++ cpp2rust/converter/rules/matcher.cpp | 22 ++++++++++------------ cpp2rust/converter/rules/matcher.h | 6 +++--- cpp2rust/converter/rules/registry.cpp | 4 ++-- cpp2rust/converter/rules/rules_loader.cpp | 2 ++ 6 files changed, 41 insertions(+), 17 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 34e85773d..e284b28fb 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -139,6 +139,28 @@ std::string Converter::GetUnboxedTypeAsString(clang::QualType qual_type) { return ToString(qual_type); } +std::string +Converter::GetTemplateArgumentAsString(const clang::TemplateArgument &arg) { + switch (arg.getKind()) { + case clang::TemplateArgument::Type: + return GetUnboxedTypeAsString(arg.getAsType()); + case clang::TemplateArgument::Integral: + case clang::TemplateArgument::NullPtr: + case clang::TemplateArgument::Declaration: + case clang::TemplateArgument::StructuralValue: { + auto expr = GetSema().BuildExpressionFromNonTypeTemplateArgument( + arg, clang::SourceLocation()); + assert(expr.isUsable() && "cannot build non-type template argument"); + Buffer buf(*this); + Convert(expr.get()); + return std::move(buf).str(); + } + default: + assert(0 && "template parameter is not bound to a type or a value"); + return {}; + } +} + bool Converter::ConvertMappedType(clang::QualType qual_type) { std::string type_as_string = Mapper::Map(*this, qual_type); if (type_as_string == token::kIgnoreRule) { diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 2bc85cb91..28fa6ed71 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -63,6 +63,8 @@ class Converter : public clang::RecursiveASTVisitor { virtual std::string GetUnboxedTypeAsString(clang::QualType qual_type); + std::string GetTemplateArgumentAsString(const clang::TemplateArgument &arg); + bool VisitRecoveryExpr(clang::RecoveryExpr *expr); virtual void EmitFilePreamble(); diff --git a/cpp2rust/converter/rules/matcher.cpp b/cpp2rust/converter/rules/matcher.cpp index 7d79dcedb..7fd2ff12a 100644 --- a/cpp2rust/converter/rules/matcher.cpp +++ b/cpp2rust/converter/rules/matcher.cpp @@ -12,22 +12,20 @@ namespace cpp2rust::Matcher { std::string MapBinding(Converter &converter, const Bindings &bindings, unsigned n) { - auto type = bindings.at(n); - assert(!type.isNull() && "template parameter is not bound to a type"); - return converter.GetUnboxedTypeAsString(type); + return converter.GetTemplateArgumentAsString(bindings.at(n)); } -// Substitutes concrete types into a target template string using the provided -// type mapping. Each template parameter in `tgt_template` is replaced with its -// corresponding instantiated type from `types`. +// Substitutes template arguments into a target template string. Each template +// parameter in `tgt_template` is replaced with its corresponding argument from +// `bindings`, which is either a type or a value. // // Example: -// types = { int } -// tgt_template = "Vec" -// result = "Vec" -std::string InstantiateTgt(Converter &converter, const Bindings &types, +// bindings = { int, 4 } +// tgt_template = "[T1; T2]" +// result = "[i32; 4_usize]" +std::string InstantiateTgt(Converter &converter, const Bindings &bindings, const std::string &tgt_template) { - assert(types.size() <= TranslationRule::kMaxGenerics && + assert(bindings.size() <= TranslationRule::kMaxGenerics && "template placeholder exceeds kMaxGenerics"); std::string instantiated_template = tgt_template; std::string::size_type pos = 0; @@ -40,7 +38,7 @@ std::string InstantiateTgt(Converter &converter, const Bindings &types, continue; } auto repl = - MapBinding(converter, types, instantiated_template[pos + 1] - '1'); + MapBinding(converter, bindings, instantiated_template[pos + 1] - '1'); instantiated_template.replace(pos, 2, repl); pos += repl.length(); } diff --git a/cpp2rust/converter/rules/matcher.h b/cpp2rust/converter/rules/matcher.h index 9730e8e0c..2b82100b6 100644 --- a/cpp2rust/converter/rules/matcher.h +++ b/cpp2rust/converter/rules/matcher.h @@ -6,7 +6,7 @@ #include #include #include -#include +#include #include #include @@ -19,13 +19,13 @@ class Converter; } namespace cpp2rust::Matcher { -using Bindings = std::vector; +using Bindings = std::vector; template using Match = std::pair; std::string MapBinding(Converter &converter, const Bindings &bindings, unsigned n); -std::string InstantiateTgt(Converter &converter, const Bindings &types, +std::string InstantiateTgt(Converter &converter, const Bindings &bindings, const std::string &tgt_template); } // namespace cpp2rust::Matcher diff --git a/cpp2rust/converter/rules/registry.cpp b/cpp2rust/converter/rules/registry.cpp index 4cbd5fcf2..c4aabadcc 100644 --- a/cpp2rust/converter/rules/registry.cpp +++ b/cpp2rust/converter/rules/registry.cpp @@ -265,11 +265,11 @@ Matcher::Bindings getBindings(const clang::NamedDecl *rule, auto name = params->getParam(i)->getName(); unsigned n = 0; if (!name.consume_front("T") || name.getAsInteger(10, n) || - args[i].getKind() != clang::TemplateArgument::Type) { + args[i].getKind() == clang::TemplateArgument::Pack) { continue; } bindings.resize(std::max(bindings.size(), n)); - bindings[n - 1] = args[i].getAsType(); + bindings[n - 1] = args[i]; } return bindings; } diff --git a/cpp2rust/converter/rules/rules_loader.cpp b/cpp2rust/converter/rules/rules_loader.cpp index 044a389d3..1373ce9da 100644 --- a/cpp2rust/converter/rules/rules_loader.cpp +++ b/cpp2rust/converter/rules/rules_loader.cpp @@ -237,6 +237,8 @@ class RuleUsageCollector case clang::TemplateArgument::Null: case clang::TemplateArgument::Integral: case clang::TemplateArgument::NullPtr: + case clang::TemplateArgument::Declaration: + case clang::TemplateArgument::StructuralValue: case clang::TemplateArgument::Expression: case clang::TemplateArgument::Template: break; From a219a3105ca2f2e9f86ecccc3a47fcbb76b4e4de Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 10:04:48 +0100 Subject: [PATCH 03/21] Update tests --- tests/unit/lambda_as_field.cpp | 2 - tests/unit/lambda_decltype_type.cpp | 2 - tests/unit/out/refcount/lambda_as_field.rs | 100 ++++++++++++------ .../unit/out/refcount/lambda_decltype_type.rs | 66 +++++++++--- tests/unit/out/unsafe/lambda_as_field.rs | 77 ++++++++------ tests/unit/out/unsafe/lambda_decltype_type.rs | 56 +++++++--- 6 files changed, 199 insertions(+), 104 deletions(-) diff --git a/tests/unit/lambda_as_field.cpp b/tests/unit/lambda_as_field.cpp index 48ddeda96..a0a37ab14 100644 --- a/tests/unit/lambda_as_field.cpp +++ b/tests/unit/lambda_as_field.cpp @@ -1,6 +1,4 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++23 -// no-compile -// Blocked by https://github.com/Cpp2Rust/cpp2rust/issues/435 #include #include diff --git a/tests/unit/lambda_decltype_type.cpp b/tests/unit/lambda_decltype_type.cpp index 05b946a6d..45b03f791 100644 --- a/tests/unit/lambda_decltype_type.cpp +++ b/tests/unit/lambda_decltype_type.cpp @@ -1,6 +1,4 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++23 -// no-compile -// Blocked by https://github.com/Cpp2Rust/cpp2rust/issues/435 #include template struct Sorted { diff --git a/tests/unit/out/refcount/lambda_as_field.rs b/tests/unit/out/refcount/lambda_as_field.rs index e2087334d..4507fd71f 100644 --- a/tests/unit/out/refcount/lambda_as_field.rs +++ b/tests/unit/out/refcount/lambda_as_field.rs @@ -8,15 +8,15 @@ use std::os::fd::AsFd; use std::rc::{Rc, Weak}; #[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Destructor)] #[byte_size(1)] -pub struct Guard__lambda_at_lambda_as_field_cpp______ { +pub struct Guard__lambda_at_lambda_as_field_cpp_34_13__ { #[offset(0)] #[byte_size(1)] pub f: FnPtr, } -impl Default for Guard__lambda_at_lambda_as_field_cpp______ { +impl Default for Guard__lambda_at_lambda_as_field_cpp_34_13__ { fn default() -> Self { { - Guard__lambda_at_lambda_as_field_cpp______ { + Guard__lambda_at_lambda_as_field_cpp_34_13__ { f: FnPtr::::new(|| { (*count_0.with(Value::clone).borrow_mut()).postfix_inc(); }), @@ -24,19 +24,26 @@ impl Default for Guard__lambda_at_lambda_as_field_cpp______ { } } } +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Destructor, Default)] +#[byte_size(8)] +pub struct Guard__lambda_at_lambda_as_field_cpp_45_13__ { + #[offset(0)] + #[byte_size(8)] + pub f: FnPtr, +} #[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg)] #[byte_size(8)] -pub struct Holder__lambda_at_lambda_as_field_cpp______ { +pub struct Holder__lambda_at_lambda_as_field_cpp_39_12__ { #[offset(0)] #[byte_size(1)] pub f: FnPtr i32>, #[offset(4)] pub calls: i32, } -impl Default for Holder__lambda_at_lambda_as_field_cpp______ { +impl Default for Holder__lambda_at_lambda_as_field_cpp_39_12__ { fn default() -> Self { { - Holder__lambda_at_lambda_as_field_cpp______ { + Holder__lambda_at_lambda_as_field_cpp_39_12__ { f: FnPtr:: i32>::new(|mut x: i32| -> i32 { { return (x + 1); @@ -47,16 +54,25 @@ impl Default for Holder__lambda_at_lambda_as_field_cpp______ { } } } +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(8)] +pub struct Holder__lambda_at_lambda_as_field_cpp_51_12__ { + #[offset(0)] + #[byte_size(4)] + pub f: FnPtr i32>, + #[offset(4)] + pub calls: i32, +} #[derive(Record, ByteRepr, FnPtrArg, MoveCtor)] #[byte_size(8)] -pub struct Moving__lambda_at_lambda_as_field_cpp______ { +pub struct Moving__lambda_at_lambda_as_field_cpp_64_12__ { #[offset(0)] #[byte_size(1)] pub f: FnPtr i32>, #[offset(4)] pub moves: i32, } -impl Moving__lambda_at_lambda_as_field_cpp______ { +impl Moving__lambda_at_lambda_as_field_cpp_64_12__ { pub fn new(f: FnPtr i32>) -> Self { let f: Value i32>> = Rc::new(RefCell::new(f)); Self { @@ -64,17 +80,17 @@ impl Moving__lambda_at_lambda_as_field_cpp______ { moves: 0, } } - pub fn move_from(o: Ptr) -> Self { + pub fn move_from(o: Ptr) -> Self { Self { f: (*o.upgrade().deref()).f.move_from(), moves: (o.with(|__s| __s.moves) + 1), } } } -impl Default for Moving__lambda_at_lambda_as_field_cpp______ { +impl Default for Moving__lambda_at_lambda_as_field_cpp_64_12__ { fn default() -> Self { { - Moving__lambda_at_lambda_as_field_cpp______ { + Moving__lambda_at_lambda_as_field_cpp_64_12__ { f: FnPtr:: i32>::new(|mut x: i32| -> i32 { { return (x * 2); @@ -118,8 +134,8 @@ pub fn main() { } fn main_0() -> i32 { { - let g: Value = - Rc::new(RefCell::new(Guard__lambda_at_lambda_as_field_cpp______ { + let g: Value = + Rc::new(RefCell::new(Guard__lambda_at_lambda_as_field_cpp_34_13__ { f: FnPtr::::new(|| { (*count_0.with(Value::clone).borrow_mut()).postfix_inc(); }), @@ -128,23 +144,24 @@ fn main_0() -> i32 { assert!((count_0.with(|rc| *rc.borrow()) == 0)); } assert!((count_0.with(|rc| *rc.borrow()) == 1)); - let n: Value = - Rc::new(RefCell::new(Holder__lambda_at_lambda_as_field_cpp______ { + let n: Value = Rc::new(RefCell::new( + Holder__lambda_at_lambda_as_field_cpp_39_12__ { f: FnPtr:: i32>::new(|mut x: i32| -> i32 { { return (x + 1); } }), calls: 0, - })); + }, + )); assert!( - (({ Holder__lambda_at_lambda_as_field_cpp______Impl::call(&n.as_pointer(), 2,) }) == 3) + (({ Holder__lambda_at_lambda_as_field_cpp_39_12__Impl::call(&n.as_pointer(), 2,) }) == 3) ); assert!(({ (*n.borrow()).calls } == 1)); let cleaned: Value = Rc::new(RefCell::new(0)); { - let g: Value = - Rc::new(RefCell::new(Guard__lambda_at_lambda_as_field_cpp______ { + let g: Value = + Rc::new(RefCell::new(Guard__lambda_at_lambda_as_field_cpp_45_13__ { f: lambda!( { let cleaned: Ptr = cleaned.as_pointer(); @@ -159,8 +176,8 @@ fn main_0() -> i32 { } assert!(((*cleaned.borrow()) == 1)); let factor: Value = Rc::new(RefCell::new(3)); - let h: Value = - Rc::new(RefCell::new(Holder__lambda_at_lambda_as_field_cpp______ { + let h: Value = Rc::new(RefCell::new( + Holder__lambda_at_lambda_as_field_cpp_51_12__ { f: lambda!( { let factor: Value = Rc::new(RefCell::new((*factor.borrow()))); @@ -170,13 +187,14 @@ fn main_0() -> i32 { } ), calls: 0, - })); + }, + )); (*factor.borrow_mut()) = 100; assert!( - (({ Holder__lambda_at_lambda_as_field_cpp______Impl::call(&h.as_pointer(), 2,) }) == 6) + (({ Holder__lambda_at_lambda_as_field_cpp_51_12__Impl::call(&h.as_pointer(), 2,) }) == 6) ); assert!( - (({ Holder__lambda_at_lambda_as_field_cpp______Impl::call(&h.as_pointer(), 5,) }) == 15) + (({ Holder__lambda_at_lambda_as_field_cpp_51_12__Impl::call(&h.as_pointer(), 5,) }) == 15) ); assert!(({ (*h.borrow()).calls } == 2)); let w: Value i32>> = Rc::new(RefCell::new( @@ -196,8 +214,8 @@ fn main_0() -> i32 { let ww: Value i32>> = Rc::new(RefCell::new(({ wrap_2((*w.borrow()).copy_from()) }))); assert!((({ (*ww.borrow()).call(2,) }) == 202)); - let m: Value = Rc::new(RefCell::new( - Moving__lambda_at_lambda_as_field_cpp______::new({ + let m: Value = Rc::new(RefCell::new( + Moving__lambda_at_lambda_as_field_cpp_64_12__::new({ FnPtr:: i32>::new(|mut x: i32| -> i32 { { return (x * 2); @@ -205,36 +223,50 @@ fn main_0() -> i32 { }) }), )); - let m2: Value = Rc::new(RefCell::new( - Moving__lambda_at_lambda_as_field_cpp______::move_from({ m.as_pointer() }), + let m2: Value = Rc::new(RefCell::new( + Moving__lambda_at_lambda_as_field_cpp_64_12__::move_from({ m.as_pointer() }), )); assert!((({ (*m2.borrow()).f.call(3,) }) == 6)); assert!(({ (*m2.borrow()).moves } == 1)); return 0; } -pub trait Guard__lambda_at_lambda_as_field_cpp______Impl { +pub trait Guard__lambda_at_lambda_as_field_cpp_34_13__Impl { fn destructor(&self); } -impl Guard__lambda_at_lambda_as_field_cpp______Impl - for Ptr +impl Guard__lambda_at_lambda_as_field_cpp_34_13__Impl + for Ptr { fn destructor(&self) { ({ (*(*self).upgrade().deref()).f.call() }); } +} +pub trait Guard__lambda_at_lambda_as_field_cpp_45_13__Impl { + fn destructor(&self); +} +impl Guard__lambda_at_lambda_as_field_cpp_45_13__Impl + for Ptr +{ fn destructor(&self) { ({ (*(*self).upgrade().deref()).f.call() }); } } -pub trait Holder__lambda_at_lambda_as_field_cpp______Impl { +pub trait Holder__lambda_at_lambda_as_field_cpp_39_12__Impl { fn call(&self, x: i32) -> i32; } -impl Holder__lambda_at_lambda_as_field_cpp______Impl - for Ptr +impl Holder__lambda_at_lambda_as_field_cpp_39_12__Impl + for Ptr { fn call(&self, mut x: i32) -> i32 { field!((*self), calls).with_mut(|__v| __v.postfix_inc()); return ({ (*(*self).upgrade().deref()).f.call(x) }); } +} +pub trait Holder__lambda_at_lambda_as_field_cpp_51_12__Impl { + fn call(&self, x: i32) -> i32; +} +impl Holder__lambda_at_lambda_as_field_cpp_51_12__Impl + for Ptr +{ fn call(&self, mut x: i32) -> i32 { field!((*self), calls).with_mut(|__v| __v.postfix_inc()); return ({ (*(*self).upgrade().deref()).f.call(x) }); diff --git a/tests/unit/out/refcount/lambda_decltype_type.rs b/tests/unit/out/refcount/lambda_decltype_type.rs index 72b906d4a..823c2e3bf 100644 --- a/tests/unit/out/refcount/lambda_decltype_type.rs +++ b/tests/unit/out/refcount/lambda_decltype_type.rs @@ -8,7 +8,7 @@ use std::os::fd::AsFd; use std::rc::{Rc, Weak}; #[derive(DeepClone, Record, ByteRepr, VaArg, FnPtrArg)] #[byte_size(24)] -pub struct Sorted__lambda_at_lambda_decltype_type_cpp______ { +pub struct Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ { #[offset(0)] #[byte_size(16)] pub items: Value>, @@ -18,10 +18,10 @@ pub struct Sorted__lambda_at_lambda_decltype_type_cpp______ { #[byte_size(1)] pub cmp: FnPtr bool>, } -impl Default for Sorted__lambda_at_lambda_decltype_type_cpp______ { +impl Default for Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ { fn default() -> Self { { - Sorted__lambda_at_lambda_decltype_type_cpp______ { + Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ { items: Rc::new(RefCell::new((0..4).map(|_| 0_i32).collect::>())), size: 0, cmp: FnPtr:: bool>::new(|mut a: i32, mut b: i32| -> bool { @@ -33,6 +33,33 @@ impl Default for Sorted__lambda_at_lambda_decltype_type_cpp______ { } } } +#[derive(DeepClone, Record, ByteRepr, VaArg, FnPtrArg)] +#[byte_size(24)] +pub struct Sorted__lambda_at_lambda_decltype_type_cpp_19_23__ { + #[offset(0)] + #[byte_size(16)] + pub items: Value>, + #[offset(16)] + pub size: i32, + #[offset(20)] + #[byte_size(1)] + pub cmp: FnPtr bool>, +} +impl Default for Sorted__lambda_at_lambda_decltype_type_cpp_19_23__ { + fn default() -> Self { + { + Sorted__lambda_at_lambda_decltype_type_cpp_19_23__ { + items: Rc::new(RefCell::new((0..4).map(|_| 0_i32).collect::>())), + size: 0, + cmp: FnPtr:: bool>::new(|mut a: i32, mut b: i32| -> bool { + { + return (a < b); + } + }), + } + } + } +} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -46,12 +73,12 @@ fn main_0() -> i32 { } }, ))); - let desc: Value = Rc::new(RefCell::new( - ::default(), + let desc: Value = Rc::new(RefCell::new( + ::default(), )); - ({ Sorted__lambda_at_lambda_decltype_type_cpp______Impl::insert(&desc.as_pointer(), 2) }); - ({ Sorted__lambda_at_lambda_decltype_type_cpp______Impl::insert(&desc.as_pointer(), 7) }); - ({ Sorted__lambda_at_lambda_decltype_type_cpp______Impl::insert(&desc.as_pointer(), 4) }); + ({ Sorted__lambda_at_lambda_decltype_type_cpp_22_18__Impl::insert(&desc.as_pointer(), 2) }); + ({ Sorted__lambda_at_lambda_decltype_type_cpp_22_18__Impl::insert(&desc.as_pointer(), 7) }); + ({ Sorted__lambda_at_lambda_decltype_type_cpp_22_18__Impl::insert(&desc.as_pointer(), 4) }); assert!( ((elem!( (array_field_ptr!(desc.as_pointer(), items) as Ptr::), @@ -76,12 +103,12 @@ fn main_0() -> i32 { .read()) == 2) ); - let asc: Value = Rc::new(RefCell::new( - ::default(), + let asc: Value = Rc::new(RefCell::new( + ::default(), )); - ({ Sorted__lambda_at_lambda_decltype_type_cpp______Impl::insert(&asc.as_pointer(), 2) }); - ({ Sorted__lambda_at_lambda_decltype_type_cpp______Impl::insert(&asc.as_pointer(), 7) }); - ({ Sorted__lambda_at_lambda_decltype_type_cpp______Impl::insert(&asc.as_pointer(), 4) }); + ({ Sorted__lambda_at_lambda_decltype_type_cpp_19_23__Impl::insert(&asc.as_pointer(), 2) }); + ({ Sorted__lambda_at_lambda_decltype_type_cpp_19_23__Impl::insert(&asc.as_pointer(), 7) }); + ({ Sorted__lambda_at_lambda_decltype_type_cpp_19_23__Impl::insert(&asc.as_pointer(), 4) }); assert!(((elem!((array_field_ptr!(asc.as_pointer(), items) as Ptr::), 0).read()) == 2)); assert!(((elem!((array_field_ptr!(asc.as_pointer(), items) as Ptr::), 1).read()) == 4)); assert!(((elem!((array_field_ptr!(asc.as_pointer(), items) as Ptr::), 2).read()) == 7)); @@ -116,11 +143,11 @@ fn main_0() -> i32 { assert!((({ (*less.borrow()).call(1, 3,) }) as bool)); return 0; } -pub trait Sorted__lambda_at_lambda_decltype_type_cpp______Impl { +pub trait Sorted__lambda_at_lambda_decltype_type_cpp_19_23__Impl { fn insert(&self, v: i32); } -impl Sorted__lambda_at_lambda_decltype_type_cpp______Impl - for Ptr +impl Sorted__lambda_at_lambda_decltype_type_cpp_19_23__Impl + for Ptr { fn insert(&self, mut v: i32) { let mut i: i32 = (*self).with(|__s| __s.size); @@ -139,6 +166,13 @@ impl Sorted__lambda_at_lambda_decltype_type_cpp______Impl elem!((array_field_ptr!((*self), items) as Ptr::), i).write(v); field!((*self), size).with_mut(|__v| __v.postfix_inc()); } +} +pub trait Sorted__lambda_at_lambda_decltype_type_cpp_22_18__Impl { + fn insert(&self, v: i32); +} +impl Sorted__lambda_at_lambda_decltype_type_cpp_22_18__Impl + for Ptr +{ fn insert(&self, mut v: i32) { let mut i: i32 = (*self).with(|__s| __s.size); 'loop_: while (i > 0) diff --git a/tests/unit/out/unsafe/lambda_as_field.rs b/tests/unit/out/unsafe/lambda_as_field.rs index d6e589f5e..e4dd7672d 100644 --- a/tests/unit/out/unsafe/lambda_as_field.rs +++ b/tests/unit/out/unsafe/lambda_as_field.rs @@ -8,18 +8,18 @@ use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] #[derive(Clone, VaArg, FnPtrArg, DestructorUnsafe)] -pub struct Guard__lambda_at_lambda_as_field_cpp______ { +pub struct Guard__lambda_at_lambda_as_field_cpp_34_13__ { pub f: FnPtr, } -impl Guard__lambda_at_lambda_as_field_cpp______ { +impl Guard__lambda_at_lambda_as_field_cpp_34_13__ { pub unsafe fn destructor(&mut self) { (unsafe { self.f.call() }); } } -impl Default for Guard__lambda_at_lambda_as_field_cpp______ { +impl Default for Guard__lambda_at_lambda_as_field_cpp_34_13__ { fn default() -> Self { unsafe { - Guard__lambda_at_lambda_as_field_cpp______ { + Guard__lambda_at_lambda_as_field_cpp_34_13__ { f: FnPtr::::new(|| unsafe { (*std::cell::LazyCell::force_mut(&mut *&raw mut count_0)).postfix_inc(); }), @@ -27,27 +27,32 @@ impl Default for Guard__lambda_at_lambda_as_field_cpp______ { } } } -impl Guard__lambda_at_lambda_as_field_cpp______ { +#[repr(C)] +#[derive(Clone, VaArg, FnPtrArg, DestructorUnsafe, Default)] +pub struct Guard__lambda_at_lambda_as_field_cpp_45_13__ { + pub f: FnPtr, +} +impl Guard__lambda_at_lambda_as_field_cpp_45_13__ { pub unsafe fn destructor(&mut self) { (unsafe { self.f.call() }); } } #[repr(C)] -#[derive(Clone, VaArg, FnPtrArg)] -pub struct Holder__lambda_at_lambda_as_field_cpp______ { +#[derive(Copy, Clone, VaArg, FnPtrArg)] +pub struct Holder__lambda_at_lambda_as_field_cpp_39_12__ { pub f: FnPtr i32>, pub calls: i32, } -impl Holder__lambda_at_lambda_as_field_cpp______ { +impl Holder__lambda_at_lambda_as_field_cpp_39_12__ { pub unsafe fn call(&mut self, mut x: i32) -> i32 { self.calls.postfix_inc(); return (unsafe { self.f.call(x) }); } } -impl Default for Holder__lambda_at_lambda_as_field_cpp______ { +impl Default for Holder__lambda_at_lambda_as_field_cpp_39_12__ { fn default() -> Self { unsafe { - Holder__lambda_at_lambda_as_field_cpp______ { + Holder__lambda_at_lambda_as_field_cpp_39_12__ { f: FnPtr:: i32>::new(|mut x: i32| -> i32 { unsafe { return ((x) + (1)); @@ -58,7 +63,13 @@ impl Default for Holder__lambda_at_lambda_as_field_cpp______ { } } } -impl Holder__lambda_at_lambda_as_field_cpp______ { +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct Holder__lambda_at_lambda_as_field_cpp_51_12__ { + pub f: FnPtr i32>, + pub calls: i32, +} +impl Holder__lambda_at_lambda_as_field_cpp_51_12__ { pub unsafe fn call(&mut self, mut x: i32) -> i32 { self.calls.postfix_inc(); return (unsafe { self.f.call(x) }); @@ -66,11 +77,11 @@ impl Holder__lambda_at_lambda_as_field_cpp______ { } #[repr(C)] #[derive(FnPtrArg, MoveCtorUnsafe)] -pub struct Moving__lambda_at_lambda_as_field_cpp______ { +pub struct Moving__lambda_at_lambda_as_field_cpp_64_12__ { pub f: FnPtr i32>, pub moves: i32, } -impl Moving__lambda_at_lambda_as_field_cpp______ { +impl Moving__lambda_at_lambda_as_field_cpp_64_12__ { pub unsafe fn new(mut f: FnPtr i32>) -> Self { let mut this = Self { f: f.copy_from(), @@ -78,7 +89,7 @@ impl Moving__lambda_at_lambda_as_field_cpp______ { }; this } - pub unsafe fn move_from(o: *mut Moving__lambda_at_lambda_as_field_cpp______) -> Self { + pub unsafe fn move_from(o: *mut Moving__lambda_at_lambda_as_field_cpp_64_12__) -> Self { let mut this = Self { f: (*o).f.move_from(), moves: (((*o).moves) + (1)), @@ -86,10 +97,10 @@ impl Moving__lambda_at_lambda_as_field_cpp______ { this } } -impl Default for Moving__lambda_at_lambda_as_field_cpp______ { +impl Default for Moving__lambda_at_lambda_as_field_cpp_64_12__ { fn default() -> Self { unsafe { - Moving__lambda_at_lambda_as_field_cpp______ { + Moving__lambda_at_lambda_as_field_cpp_64_12__ { f: FnPtr:: i32>::new(|mut x: i32| -> i32 { unsafe { return ((x) * (2)); @@ -129,21 +140,21 @@ pub fn main() { } unsafe fn main_0() -> i32 { { - let mut g: Guard__lambda_at_lambda_as_field_cpp______ = - Guard__lambda_at_lambda_as_field_cpp______ { + let mut g: Guard__lambda_at_lambda_as_field_cpp_34_13__ = + Guard__lambda_at_lambda_as_field_cpp_34_13__ { f: FnPtr::::new(|| unsafe { (*std::cell::LazyCell::force_mut(&mut *&raw mut count_0)).postfix_inc(); }), }; let _dtor_g = ScopedDestructorUnsafe::new( &raw mut g, - Guard__lambda_at_lambda_as_field_cpp______::destructor, + Guard__lambda_at_lambda_as_field_cpp_34_13__::destructor, ); assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut count_0)) == (0))); } assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut count_0)) == (1))); - let mut n: Holder__lambda_at_lambda_as_field_cpp______ = - Holder__lambda_at_lambda_as_field_cpp______ { + let mut n: Holder__lambda_at_lambda_as_field_cpp_39_12__ = + Holder__lambda_at_lambda_as_field_cpp_39_12__ { f: FnPtr:: i32>::new(|mut x: i32| -> i32 { unsafe { return ((x) + (1)); @@ -151,12 +162,12 @@ unsafe fn main_0() -> i32 { }), calls: 0, }; - assert!(((unsafe { Holder__lambda_at_lambda_as_field_cpp______::call(&mut n, 2,) }) == (3))); + assert!(((unsafe { Holder__lambda_at_lambda_as_field_cpp_39_12__::call(&mut n, 2,) }) == (3))); assert!(((n.calls) == (1))); let mut cleaned: i32 = 0; { - let mut g: Guard__lambda_at_lambda_as_field_cpp______ = - Guard__lambda_at_lambda_as_field_cpp______ { + let mut g: Guard__lambda_at_lambda_as_field_cpp_45_13__ = + Guard__lambda_at_lambda_as_field_cpp_45_13__ { f: lambda_unsafe!( { let cleaned: *mut i32 = &mut cleaned; @@ -168,14 +179,14 @@ unsafe fn main_0() -> i32 { }; let _dtor_g = ScopedDestructorUnsafe::new( &raw mut g, - Guard__lambda_at_lambda_as_field_cpp______::destructor, + Guard__lambda_at_lambda_as_field_cpp_45_13__::destructor, ); assert!(((cleaned) == (0))); } assert!(((cleaned) == (1))); let mut factor: i32 = 3; - let mut h: Holder__lambda_at_lambda_as_field_cpp______ = - Holder__lambda_at_lambda_as_field_cpp______ { + let mut h: Holder__lambda_at_lambda_as_field_cpp_51_12__ = + Holder__lambda_at_lambda_as_field_cpp_51_12__ { f: lambda_unsafe!( { let factor: i32 = factor; @@ -187,8 +198,8 @@ unsafe fn main_0() -> i32 { calls: 0, }; factor = 100; - assert!(((unsafe { Holder__lambda_at_lambda_as_field_cpp______::call(&mut h, 2,) }) == (6))); - assert!(((unsafe { Holder__lambda_at_lambda_as_field_cpp______::call(&mut h, 5,) }) == (15))); + assert!(((unsafe { Holder__lambda_at_lambda_as_field_cpp_51_12__::call(&mut h, 2,) }) == (6))); + assert!(((unsafe { Holder__lambda_at_lambda_as_field_cpp_51_12__::call(&mut h, 5,) }) == (15))); assert!(((h.calls) == (2))); let mut w: FnPtr i32> = (unsafe { wrap_1(lambda_unsafe!( @@ -204,16 +215,16 @@ unsafe fn main_0() -> i32 { assert!(((unsafe { w.call(2,) }) == (201))); let mut ww: FnPtr i32> = (unsafe { wrap_2(w.copy_from()) }); assert!(((unsafe { ww.call(2,) }) == (202))); - let mut m: Moving__lambda_at_lambda_as_field_cpp______ = - Moving__lambda_at_lambda_as_field_cpp______::new({ + let mut m: Moving__lambda_at_lambda_as_field_cpp_64_12__ = + Moving__lambda_at_lambda_as_field_cpp_64_12__::new({ FnPtr:: i32>::new(|mut x: i32| -> i32 { unsafe { return ((x) * (2)); } }) }); - let mut m2: Moving__lambda_at_lambda_as_field_cpp______ = - Moving__lambda_at_lambda_as_field_cpp______::move_from({ &mut m }); + let mut m2: Moving__lambda_at_lambda_as_field_cpp_64_12__ = + Moving__lambda_at_lambda_as_field_cpp_64_12__::move_from({ &mut m }); assert!(((unsafe { m2.f.call(3,) }) == (6))); assert!(((m2.moves) == (1))); return 0; diff --git a/tests/unit/out/unsafe/lambda_decltype_type.rs b/tests/unit/out/unsafe/lambda_decltype_type.rs index 90fe68c77..540bf376e 100644 --- a/tests/unit/out/unsafe/lambda_decltype_type.rs +++ b/tests/unit/out/unsafe/lambda_decltype_type.rs @@ -7,13 +7,13 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] -#[derive(Clone, VaArg, FnPtrArg)] -pub struct Sorted__lambda_at_lambda_decltype_type_cpp______ { +#[derive(Copy, Clone, VaArg, FnPtrArg)] +pub struct Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ { pub items: [i32; 4], pub size: i32, pub cmp: FnPtr bool>, } -impl Sorted__lambda_at_lambda_decltype_type_cpp______ { +impl Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ { pub unsafe fn insert(&mut self, mut v: i32) { let mut i: i32 = self.size; 'loop_: while ((i) > (0)) @@ -29,10 +29,10 @@ impl Sorted__lambda_at_lambda_decltype_type_cpp______ { self.size.postfix_inc(); } } -impl Default for Sorted__lambda_at_lambda_decltype_type_cpp______ { +impl Default for Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ { fn default() -> Self { unsafe { - Sorted__lambda_at_lambda_decltype_type_cpp______ { + Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ { items: [0_i32; 4], size: 0, cmp: FnPtr:: bool>::new(|mut a: i32, mut b: i32| -> bool { @@ -44,7 +44,14 @@ impl Default for Sorted__lambda_at_lambda_decltype_type_cpp______ { } } } -impl Sorted__lambda_at_lambda_decltype_type_cpp______ { +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg)] +pub struct Sorted__lambda_at_lambda_decltype_type_cpp_19_23__ { + pub items: [i32; 4], + pub size: i32, + pub cmp: FnPtr bool>, +} +impl Sorted__lambda_at_lambda_decltype_type_cpp_19_23__ { pub unsafe fn insert(&mut self, mut v: i32) { let mut i: i32 = self.size; 'loop_: while ((i) > (0)) @@ -60,6 +67,21 @@ impl Sorted__lambda_at_lambda_decltype_type_cpp______ { self.size.postfix_inc(); } } +impl Default for Sorted__lambda_at_lambda_decltype_type_cpp_19_23__ { + fn default() -> Self { + unsafe { + Sorted__lambda_at_lambda_decltype_type_cpp_19_23__ { + items: [0_i32; 4], + size: 0, + cmp: FnPtr:: bool>::new(|mut a: i32, mut b: i32| -> bool { + unsafe { + return ((a) < (b)); + } + }), + } + } + } +} pub fn main() { unsafe { __cpp2rust_init_globals(); @@ -73,19 +95,19 @@ unsafe fn main_0() -> i32 { return ((a) > (b)); } }); - let mut desc: Sorted__lambda_at_lambda_decltype_type_cpp______ = - ::default(); - (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp______::insert(&mut desc, 2) }); - (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp______::insert(&mut desc, 7) }); - (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp______::insert(&mut desc, 4) }); + let mut desc: Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ = + ::default(); + (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp_22_18__::insert(&mut desc, 2) }); + (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp_22_18__::insert(&mut desc, 7) }); + (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp_22_18__::insert(&mut desc, 4) }); assert!(((desc.items[(0) as usize]) == (7))); assert!(((desc.items[(1) as usize]) == (4))); assert!(((desc.items[(2) as usize]) == (2))); - let mut asc: Sorted__lambda_at_lambda_decltype_type_cpp______ = - ::default(); - (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp______::insert(&mut asc, 2) }); - (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp______::insert(&mut asc, 7) }); - (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp______::insert(&mut asc, 4) }); + let mut asc: Sorted__lambda_at_lambda_decltype_type_cpp_19_23__ = + ::default(); + (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp_19_23__::insert(&mut asc, 2) }); + (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp_19_23__::insert(&mut asc, 7) }); + (unsafe { Sorted__lambda_at_lambda_decltype_type_cpp_19_23__::insert(&mut asc, 4) }); assert!(((asc.items[(0) as usize]) == (2))); assert!(((asc.items[(1) as usize]) == (4))); assert!(((asc.items[(2) as usize]) == (7))); @@ -103,7 +125,7 @@ unsafe fn main_0() -> i32 { return ((a) > (b)); } }); - assigned = (greater).clone(); + assigned = greater; assert!(((unsafe { assigned.call(5, 4,) }) as bool)); let mut less: FnPtr bool> = FnPtr:: bool>::new(|mut a: i32, mut b: i32| -> bool { From 4d95373e0202cc88acf05266df3fd3de79beae02 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 10:07:55 +0100 Subject: [PATCH 04/21] Records that contain lambdas don't derive Copy --- cpp2rust/converter/converter.cpp | 4 ++++ tests/unit/out/unsafe/lambda_as_field.rs | 4 ++-- tests/unit/out/unsafe/lambda_decltype_type.rs | 6 +++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index e284b28fb..5aba7cecc 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -769,6 +769,10 @@ bool Converter::IsPassThroughRule(clang::Expr *expr) const { } bool Converter::RecordDerivesCopy(const clang::RecordDecl *decl) { + if (auto cxx = llvm::dyn_cast(decl); + cxx && cxx->isLambda()) { + return false; + } if (auto rule = RuleRegistry::Search(ctx_, ctx_.getCanonicalTagType(decl)).first) { auto &derives = rule->type_info.derives; diff --git a/tests/unit/out/unsafe/lambda_as_field.rs b/tests/unit/out/unsafe/lambda_as_field.rs index e4dd7672d..cde749b37 100644 --- a/tests/unit/out/unsafe/lambda_as_field.rs +++ b/tests/unit/out/unsafe/lambda_as_field.rs @@ -38,7 +38,7 @@ impl Guard__lambda_at_lambda_as_field_cpp_45_13__ { } } #[repr(C)] -#[derive(Copy, Clone, VaArg, FnPtrArg)] +#[derive(Clone, VaArg, FnPtrArg)] pub struct Holder__lambda_at_lambda_as_field_cpp_39_12__ { pub f: FnPtr i32>, pub calls: i32, @@ -64,7 +64,7 @@ impl Default for Holder__lambda_at_lambda_as_field_cpp_39_12__ { } } #[repr(C)] -#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +#[derive(Clone, VaArg, FnPtrArg, Default)] pub struct Holder__lambda_at_lambda_as_field_cpp_51_12__ { pub f: FnPtr i32>, pub calls: i32, diff --git a/tests/unit/out/unsafe/lambda_decltype_type.rs b/tests/unit/out/unsafe/lambda_decltype_type.rs index 540bf376e..bd85885c7 100644 --- a/tests/unit/out/unsafe/lambda_decltype_type.rs +++ b/tests/unit/out/unsafe/lambda_decltype_type.rs @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] -#[derive(Copy, Clone, VaArg, FnPtrArg)] +#[derive(Clone, VaArg, FnPtrArg)] pub struct Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ { pub items: [i32; 4], pub size: i32, @@ -45,7 +45,7 @@ impl Default for Sorted__lambda_at_lambda_decltype_type_cpp_22_18__ { } } #[repr(C)] -#[derive(Copy, Clone, VaArg, FnPtrArg)] +#[derive(Clone, VaArg, FnPtrArg)] pub struct Sorted__lambda_at_lambda_decltype_type_cpp_19_23__ { pub items: [i32; 4], pub size: i32, @@ -125,7 +125,7 @@ unsafe fn main_0() -> i32 { return ((a) > (b)); } }); - assigned = greater; + assigned = (greater).clone(); assert!(((unsafe { assigned.call(5, 4,) }) as bool)); let mut less: FnPtr bool> = FnPtr:: bool>::new(|mut a: i32, mut b: i32| -> bool { From 5b15fbb0769517477ecf58cb2e4e12ae95272baf Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 10:11:43 +0100 Subject: [PATCH 05/21] Add rules for get<0> and get<1> --- rules/pair/src.cpp | 16 ++++++++++++++++ rules/pair/tgt_refcount.rs | 16 ++++++++++++++++ rules/pair/tgt_unsafe.rs | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/rules/pair/src.cpp b/rules/pair/src.cpp index 103a79970..508e96f77 100644 --- a/rules/pair/src.cpp +++ b/rules/pair/src.cpp @@ -48,3 +48,19 @@ template const T2 &f15(const std::pair &a0) { template const T1 &f16(const std::pair &a0) { return a0.first; } + +template T1 &f17(std::pair &a0) { + return std::get<0>(a0); +} + +template T2 &f18(std::pair &a0) { + return std::get<1>(a0); +} + +template const T1 &f19(const std::pair &a0) { + return std::get<0>(a0); +} + +template const T2 &f20(const std::pair &a0) { + return std::get<1>(a0); +} diff --git a/rules/pair/tgt_refcount.rs b/rules/pair/tgt_refcount.rs index 0078956c5..ecaaa7b1c 100644 --- a/rules/pair/tgt_refcount.rs +++ b/rules/pair/tgt_refcount.rs @@ -68,3 +68,19 @@ fn f15(a0: (Value, Value)) -> Value { fn f16(a0: (Value, Value)) -> Value { a0.0 } + +fn f17(a0: (Value, Value)) -> Value { + a0.0 +} + +fn f18(a0: (Value, Value)) -> Value { + a0.1 +} + +fn f19(a0: (Value, Value)) -> Value { + a0.0 +} + +fn f20(a0: (Value, Value)) -> Value { + a0.1 +} diff --git a/rules/pair/tgt_unsafe.rs b/rules/pair/tgt_unsafe.rs index 9bf460bd8..ba1a9e89d 100644 --- a/rules/pair/tgt_unsafe.rs +++ b/rules/pair/tgt_unsafe.rs @@ -37,3 +37,19 @@ unsafe fn f15(a0: (T1, T2)) -> T2 { unsafe fn f16(a0: (T1, T2)) -> T1 { a0.0 } + +unsafe fn f17(a0: (T1, T2)) -> T1 { + a0.0 +} + +unsafe fn f18(a0: (T1, T2)) -> T2 { + a0.1 +} + +unsafe fn f19(a0: (T1, T2)) -> T1 { + a0.0 +} + +unsafe fn f20(a0: (T1, T2)) -> T2 { + a0.1 +} From f01c29a71a30ebf6a18f9031e896e70411b581cc Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 10:12:54 +0100 Subject: [PATCH 06/21] Update tests --- tests/unit/nttp_distinct_specializations.cpp | 30 +++++++ .../refcount/nttp_distinct_specializations.rs | 78 +++++++++++++++++++ tests/unit/out/refcount/pair_get.rs | 30 +++++++ .../unsafe/nttp_distinct_specializations.rs | 67 ++++++++++++++++ tests/unit/out/unsafe/pair_get.rs | 29 +++++++ tests/unit/pair_get.cpp | 17 ++++ 6 files changed, 251 insertions(+) create mode 100644 tests/unit/nttp_distinct_specializations.cpp create mode 100644 tests/unit/out/refcount/nttp_distinct_specializations.rs create mode 100644 tests/unit/out/refcount/pair_get.rs create mode 100644 tests/unit/out/unsafe/nttp_distinct_specializations.rs create mode 100644 tests/unit/out/unsafe/pair_get.rs create mode 100644 tests/unit/pair_get.cpp diff --git a/tests/unit/nttp_distinct_specializations.cpp b/tests/unit/nttp_distinct_specializations.cpp new file mode 100644 index 000000000..5bb406211 --- /dev/null +++ b/tests/unit/nttp_distinct_specializations.cpp @@ -0,0 +1,30 @@ +#include + +template struct S { + int v; + int get() const { return v * N; } +}; + +template <> struct S<2> { + int v; + int w; + int get() const { return v - w; } +}; + +template int scale(int x) { return x * N; } + +template <> int scale<2>(int x) { return x - 2; } + +int main() { + S<1> s1{5}; + S<2> s2{5, 1}; + S<3> s3{5}; + assert(s1.get() == 5); + assert(s2.get() == 4); + assert(s3.get() == 15); + + assert(scale<1>(7) == 7); + assert(scale<2>(7) == 5); + assert(scale<3>(7) == 21); + return 0; +} diff --git a/tests/unit/out/refcount/nttp_distinct_specializations.rs b/tests/unit/out/refcount/nttp_distinct_specializations.rs new file mode 100644 index 000000000..c96a166f8 --- /dev/null +++ b/tests/unit/out/refcount/nttp_distinct_specializations.rs @@ -0,0 +1,78 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(8)] +pub struct S_2_ { + #[offset(0)] + pub v: i32, + #[offset(4)] + pub w: i32, +} +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] +pub struct S_1_ { + #[offset(0)] + pub v: i32, +} +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] +pub struct S_3_ { + #[offset(0)] + pub v: i32, +} +pub fn scale_0(mut x: i32) -> i32 { + return (x * 1); +} +pub fn scale_1(mut x: i32) -> i32 { + return (x * 3); +} +pub fn scale_2(mut x: i32) -> i32 { + return (x - 2); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let s1: Value = Rc::new(RefCell::new(S_1_ { v: 5 })); + let s2: Value = Rc::new(RefCell::new(S_2_ { v: 5, w: 1 })); + let s3: Value = Rc::new(RefCell::new(S_3_ { v: 5 })); + assert!((({ S_1_Impl::get(&s1.as_pointer(),) }) == 5)); + assert!((({ S_2_Impl::get(&s2.as_pointer(),) }) == 4)); + assert!((({ S_3_Impl::get(&s3.as_pointer(),) }) == 15)); + assert!((({ scale_0(7,) }) == 7)); + assert!((({ scale_2(7,) }) == 5)); + assert!((({ scale_1(7,) }) == 21)); + return 0; +} +pub trait S_1_Impl { + fn get(&self) -> i32; +} +impl S_1_Impl for Ptr { + fn get(&self) -> i32 { + return ((*self).with(|__s| __s.v) * 1); + } +} +pub trait S_2_Impl { + fn get(&self) -> i32; +} +impl S_2_Impl for Ptr { + fn get(&self) -> i32 { + return ((*self).with(|__s| __s.v) - (*self).with(|__s| __s.w)); + } +} +pub trait S_3_Impl { + fn get(&self) -> i32; +} +impl S_3_Impl for Ptr { + fn get(&self) -> i32 { + return ((*self).with(|__s| __s.v) * 3); + } +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/pair_get.rs b/tests/unit/out/refcount/pair_get.rs new file mode 100644 index 000000000..e53d9bd14 --- /dev/null +++ b/tests/unit/out/refcount/pair_get.rs @@ -0,0 +1,30 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn second_of_0(p: Ptr<(Value, Value)>) -> i32 { + return ((*p.upgrade().deref()).1.read()); +} +pub fn first_of_1(p: Ptr<(Value, Value)>) -> f64 { + return ((*p.upgrade().deref()).0.read()); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let p: Value<(Value, Value)> = Rc::new(RefCell::new(( + Rc::new(RefCell::new(1.5_f64.try_into().expect("failed conversion"))), + Rc::new(RefCell::new(2.try_into().expect("failed conversion"))), + ))); + assert!((((*p.borrow()).0.read()) == 1.5_f64)); + assert!((((*p.borrow()).1.read()) == 2)); + assert!((({ first_of_1(p.as_pointer(),) }) == 1.5_f64)); + assert!((({ second_of_0(p.as_pointer(),) }) == 2)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/nttp_distinct_specializations.rs b/tests/unit/out/unsafe/nttp_distinct_specializations.rs new file mode 100644 index 000000000..a7dccd609 --- /dev/null +++ b/tests/unit/out/unsafe/nttp_distinct_specializations.rs @@ -0,0 +1,67 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct S_2_ { + pub v: i32, + pub w: i32, +} +impl S_2_ { + pub unsafe fn get(&self) -> i32 { + return ((self.v) - (self.w)); + } +} +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct S_1_ { + pub v: i32, +} +impl S_1_ { + pub unsafe fn get(&self) -> i32 { + return ((self.v) * (1)); + } +} +#[repr(C)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +pub struct S_3_ { + pub v: i32, +} +impl S_3_ { + pub unsafe fn get(&self) -> i32 { + return ((self.v) * (3)); + } +} +pub unsafe fn scale_0(mut x: i32) -> i32 { + return ((x) * (1)); +} +pub unsafe fn scale_1(mut x: i32) -> i32 { + return ((x) * (3)); +} +pub unsafe fn scale_2(mut x: i32) -> i32 { + return ((x) - (2)); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut s1: S_1_ = S_1_ { v: 5 }; + let mut s2: S_2_ = S_2_ { v: 5, w: 1 }; + let mut s3: S_3_ = S_3_ { v: 5 }; + assert!(((unsafe { S_1_::get(&s1,) }) == (5))); + assert!(((unsafe { S_2_::get(&s2,) }) == (4))); + assert!(((unsafe { S_3_::get(&s3,) }) == (15))); + assert!(((unsafe { scale_0(7,) }) == (7))); + assert!(((unsafe { scale_2(7,) }) == (5))); + assert!(((unsafe { scale_1(7,) }) == (21))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/pair_get.rs b/tests/unit/out/unsafe/pair_get.rs new file mode 100644 index 000000000..ca342ff25 --- /dev/null +++ b/tests/unit/out/unsafe/pair_get.rs @@ -0,0 +1,29 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn second_of_0(p: *const (f64, i32)) -> i32 { + return (*(*p).1); +} +pub unsafe fn first_of_1(p: *const (f64, i32)) -> f64 { + return (*(*p).0); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut p: (f64, i32) = (1.5_f64.into(), 2.into()); + assert!(((*p.0) == (1.5_f64))); + assert!(((*p.1) == (2))); + assert!(((unsafe { first_of_1(&p,) }) == (1.5_f64))); + assert!(((unsafe { second_of_0(&p,) }) == (2))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/pair_get.cpp b/tests/unit/pair_get.cpp new file mode 100644 index 000000000..0c28cde50 --- /dev/null +++ b/tests/unit/pair_get.cpp @@ -0,0 +1,17 @@ +#include +#include + +static int second_of(const std::pair &p) { return std::get<1>(p); } + +static double first_of(const std::pair &p) { + return std::get<0>(p); +} + +int main() { + std::pair p(1.5, 2); + assert(std::get<0>(p) == 1.5); + assert(std::get<1>(p) == 2); + assert(first_of(p) == 1.5); + assert(second_of(p) == 2); + return 0; +} From 6ae42eb15aff9d80534ee533b88fc1f197dac1a9 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 10:15:20 +0100 Subject: [PATCH 07/21] Fix rules --- rules/pair/tgt_refcount.rs | 16 ++++++++-------- rules/pair/tgt_unsafe.rs | 16 ++++++++-------- tests/unit/out/refcount/pair_get.rs | 8 ++++---- tests/unit/out/unsafe/pair_get.rs | 8 ++++---- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/rules/pair/tgt_refcount.rs b/rules/pair/tgt_refcount.rs index ecaaa7b1c..5cfff3711 100644 --- a/rules/pair/tgt_refcount.rs +++ b/rules/pair/tgt_refcount.rs @@ -69,18 +69,18 @@ fn f16(a0: (Value, Value)) -> Value { a0.0 } -fn f17(a0: (Value, Value)) -> Value { - a0.0 +fn f17(a0: (Value, Value)) -> Ptr { + a0.0.as_pointer() } -fn f18(a0: (Value, Value)) -> Value { - a0.1 +fn f18(a0: (Value, Value)) -> Ptr { + a0.1.as_pointer() } -fn f19(a0: (Value, Value)) -> Value { - a0.0 +fn f19(a0: (Value, Value)) -> Ptr { + a0.0.as_pointer() } -fn f20(a0: (Value, Value)) -> Value { - a0.1 +fn f20(a0: (Value, Value)) -> Ptr { + a0.1.as_pointer() } diff --git a/rules/pair/tgt_unsafe.rs b/rules/pair/tgt_unsafe.rs index ba1a9e89d..d679f6594 100644 --- a/rules/pair/tgt_unsafe.rs +++ b/rules/pair/tgt_unsafe.rs @@ -38,18 +38,18 @@ unsafe fn f16(a0: (T1, T2)) -> T1 { a0.0 } -unsafe fn f17(a0: (T1, T2)) -> T1 { - a0.0 +unsafe fn f17(a0: &mut (T1, T2)) -> *mut T1 { + &mut a0.0 } -unsafe fn f18(a0: (T1, T2)) -> T2 { - a0.1 +unsafe fn f18(a0: &mut (T1, T2)) -> *mut T2 { + &mut a0.1 } -unsafe fn f19(a0: (T1, T2)) -> T1 { - a0.0 +unsafe fn f19(a0: &(T1, T2)) -> *const T1 { + &a0.0 } -unsafe fn f20(a0: (T1, T2)) -> T2 { - a0.1 +unsafe fn f20(a0: &(T1, T2)) -> *const T2 { + &a0.1 } diff --git a/tests/unit/out/refcount/pair_get.rs b/tests/unit/out/refcount/pair_get.rs index e53d9bd14..dc4d45cfd 100644 --- a/tests/unit/out/refcount/pair_get.rs +++ b/tests/unit/out/refcount/pair_get.rs @@ -7,10 +7,10 @@ use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; pub fn second_of_0(p: Ptr<(Value, Value)>) -> i32 { - return ((*p.upgrade().deref()).1.read()); + return ((*p.upgrade().deref()).1.as_pointer().read()); } pub fn first_of_1(p: Ptr<(Value, Value)>) -> f64 { - return ((*p.upgrade().deref()).0.read()); + return ((*p.upgrade().deref()).0.as_pointer().read()); } pub fn main() { __cpp2rust_init_globals(); @@ -21,8 +21,8 @@ fn main_0() -> i32 { Rc::new(RefCell::new(1.5_f64.try_into().expect("failed conversion"))), Rc::new(RefCell::new(2.try_into().expect("failed conversion"))), ))); - assert!((((*p.borrow()).0.read()) == 1.5_f64)); - assert!((((*p.borrow()).1.read()) == 2)); + assert!((((*p.borrow()).0.as_pointer().read()) == 1.5_f64)); + assert!((((*p.borrow()).1.as_pointer().read()) == 2)); assert!((({ first_of_1(p.as_pointer(),) }) == 1.5_f64)); assert!((({ second_of_0(p.as_pointer(),) }) == 2)); return 0; diff --git a/tests/unit/out/unsafe/pair_get.rs b/tests/unit/out/unsafe/pair_get.rs index ca342ff25..671010f58 100644 --- a/tests/unit/out/unsafe/pair_get.rs +++ b/tests/unit/out/unsafe/pair_get.rs @@ -7,10 +7,10 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn second_of_0(p: *const (f64, i32)) -> i32 { - return (*(*p).1); + return (*&(*p).1); } pub unsafe fn first_of_1(p: *const (f64, i32)) -> f64 { - return (*(*p).0); + return (*&(*p).0); } pub fn main() { unsafe { @@ -20,8 +20,8 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut p: (f64, i32) = (1.5_f64.into(), 2.into()); - assert!(((*p.0) == (1.5_f64))); - assert!(((*p.1) == (2))); + assert!(((*&mut p.0) == (1.5_f64))); + assert!(((*&mut p.1) == (2))); assert!(((unsafe { first_of_1(&p,) }) == (1.5_f64))); assert!(((unsafe { second_of_0(&p,) }) == (2))); return 0; From f6f88e23c63057c8511f92c376f74be130413670 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Tue, 29 Sep 2026 20:16:04 +0100 Subject: [PATCH 08/21] Add decomposition tests --- tests/unit/structured_binding_array.cpp | 20 ++++++ tests/unit/structured_binding_copy_ctor.cpp | 38 +++++++++++ .../unit/structured_binding_element_ctor.cpp | 63 +++++++++++++++++++ tests/unit/structured_binding_move_ctor.cpp | 48 ++++++++++++++ tests/unit/structured_binding_pair.cpp | 25 ++++++++ tests/unit/structured_binding_range_for.cpp | 31 +++++++++ tests/unit/structured_binding_ref.cpp | 36 +++++++++++ tests/unit/structured_binding_trivial.cpp | 23 +++++++ 8 files changed, 284 insertions(+) create mode 100644 tests/unit/structured_binding_array.cpp create mode 100644 tests/unit/structured_binding_copy_ctor.cpp create mode 100644 tests/unit/structured_binding_element_ctor.cpp create mode 100644 tests/unit/structured_binding_move_ctor.cpp create mode 100644 tests/unit/structured_binding_pair.cpp create mode 100644 tests/unit/structured_binding_range_for.cpp create mode 100644 tests/unit/structured_binding_ref.cpp create mode 100644 tests/unit/structured_binding_trivial.cpp diff --git a/tests/unit/structured_binding_array.cpp b/tests/unit/structured_binding_array.cpp new file mode 100644 index 000000000..b7a6fc1b6 --- /dev/null +++ b/tests/unit/structured_binding_array.cpp @@ -0,0 +1,20 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include + +int main() { + int arr[3] = {1, 2, 3}; + + auto [a, b, c] = arr; + a = 10; + assert(a == 10); + assert(b == 2); + assert(c == 3); + assert(arr[0] == 1); + + auto &[x, y, z] = arr; + x = 7; + z += y; + assert(arr[0] == 7); + assert(arr[2] == 5); + return 0; +} diff --git a/tests/unit/structured_binding_copy_ctor.cpp b/tests/unit/structured_binding_copy_ctor.cpp new file mode 100644 index 000000000..0caf645bb --- /dev/null +++ b/tests/unit/structured_binding_copy_ctor.cpp @@ -0,0 +1,38 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include + +static int copies = 0; + +struct Counted { + int x; + int y; + + Counted(int x, int y) : x(x), y(y) {} + Counted(const Counted &other) : x(other.x * 2), y(other.y * 2) { ++copies; } +}; + +static Counted make_counted() { return Counted(5, 6); } + +int main() { + Counted s(1, 2); + + auto [a, b] = s; + assert(copies == 1); + assert(a == 2); + assert(b == 4); + + auto &[ra, rb] = s; + assert(copies == 1); + assert(ra == 1); + assert(rb == 2); + + const auto &[ca, cb] = s; + assert(copies == 1); + assert(ca == 1); + + auto [pa, pb] = make_counted(); + assert(copies == 1); + assert(pa == 5); + assert(pb == 6); + return 0; +} diff --git a/tests/unit/structured_binding_element_ctor.cpp b/tests/unit/structured_binding_element_ctor.cpp new file mode 100644 index 000000000..c55d6c223 --- /dev/null +++ b/tests/unit/structured_binding_element_ctor.cpp @@ -0,0 +1,63 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include +#include + +static int copies = 0; +static int moves = 0; + +struct Elem { + int v; + + Elem(int v) : v(v) {} + Elem(const Elem &other) : v(other.v + 100) { ++copies; } + Elem(Elem &&other) : v(other.v + 1000) { + other.v = -1; + ++moves; + } +}; + +struct Two { + Elem a; + Elem b; +}; + +static Two make_two() { return Two{Elem(1), Elem(2)}; } + +int main() { + Two t{Elem(1), Elem(2)}; + int base_copies = copies; + int base_moves = moves; + + auto [a, b] = t; + assert(copies == base_copies + 2); + assert(moves == base_moves); + assert(a.v == 101); + assert(b.v == 102); + + auto &[ra, rb] = t; + assert(copies == base_copies + 2); + assert(ra.v == 1); + ra.v = 50; + assert(t.a.v == 50); + + auto [ma, mb] = std::move(t); + assert(moves == base_moves + 2); + assert(ma.v == 1050); + assert(mb.v == 1002); + assert(t.a.v == -1); + + int before_copies = copies; + int before_moves = moves; + auto [pa, pb] = make_two(); + assert(copies == before_copies); + assert(moves == before_moves); + assert(pa.v == 1); + + std::pair p{Elem(7), Elem(8)}; + before_copies = copies; + auto [x, y] = p; + assert(copies == before_copies + 2); + assert(x.v == p.first.v + 100); + assert(y.v == p.second.v + 100); + return 0; +} diff --git a/tests/unit/structured_binding_move_ctor.cpp b/tests/unit/structured_binding_move_ctor.cpp new file mode 100644 index 000000000..04bdf3694 --- /dev/null +++ b/tests/unit/structured_binding_move_ctor.cpp @@ -0,0 +1,48 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include +#include +#include + +static int copies = 0; +static int moves = 0; + +struct Movable { + int x; + int y; + + Movable(int x, int y) : x(x), y(y) {} + Movable(const Movable &other) : x(other.x), y(other.y) { ++copies; } + Movable(Movable &&other) : x(other.x), y(other.y) { + other.x = 0; + other.y = 0; + ++moves; + } +}; + +struct Holder { + std::vector xs; + std::vector ys; + + Holder extract() && { return {std::move(xs), std::move(ys)}; } +}; + +int main() { + Movable m(3, 4); + auto [a, b] = std::move(m); + assert(moves == 1); + assert(copies == 0); + assert(a == 3); + assert(b == 4); + assert(m.x == 0); + assert(m.y == 0); + + Holder h{{1, 2, 3}, {4, 5}}; + auto [ks, vs] = std::move(h).extract(); + assert(ks.size() == 3); + assert(vs.size() == 2); + assert(ks[2] == 3); + assert(vs[0] == 4); + assert(h.xs.empty()); + assert(h.ys.empty()); + return 0; +} diff --git a/tests/unit/structured_binding_pair.cpp b/tests/unit/structured_binding_pair.cpp new file mode 100644 index 000000000..08f6dc0e5 --- /dev/null +++ b/tests/unit/structured_binding_pair.cpp @@ -0,0 +1,25 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include +#include + +static std::pair make_std_pair(int x) { return {x, x > 0}; } + +int main() { + auto [value, positive] = make_std_pair(5); + assert(value == 5); + assert(positive); + + std::pair p{1, 2}; + auto [a, b] = p; + a = 10; + assert(a == 10); + assert(b == 2); + assert(p.first == 1); + + auto &[x, y] = p; + x = 3; + y += 4; + assert(p.first == 3); + assert(p.second == 6); + return 0; +} diff --git a/tests/unit/structured_binding_range_for.cpp b/tests/unit/structured_binding_range_for.cpp new file mode 100644 index 000000000..904650583 --- /dev/null +++ b/tests/unit/structured_binding_range_for.cpp @@ -0,0 +1,31 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include + +struct Pair { + int first; + int second; +}; + +int main() { + Pair arr[3] = {{1, 2}, {3, 4}, {5, 6}}; + + for (auto &[x, y] : arr) { + x += y; + } + assert(arr[0].first == 3); + assert(arr[2].first == 11); + + for (auto [x, y] : arr) { + x = 0; + y = 0; + } + assert(arr[1].first == 7); + assert(arr[1].second == 4); + + int sum = 0; + for (const auto &[x, y] : arr) { + sum += x * y; + } + assert(sum == 3 * 2 + 7 * 4 + 11 * 6); + return 0; +} diff --git a/tests/unit/structured_binding_ref.cpp b/tests/unit/structured_binding_ref.cpp new file mode 100644 index 000000000..1d2eaf004 --- /dev/null +++ b/tests/unit/structured_binding_ref.cpp @@ -0,0 +1,36 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include + +struct Triple { + int a; + bool b; + int c; +}; + +static int sum(const Triple &t) { + const auto &[x, y, z] = t; + return x + (y ? 1 : 0) + z; +} + +int main() { + Triple t{10, false, 20}; + auto &[pos, ins, nod] = t; + pos = 11; + ins = true; + nod += 1; + assert(t.a == 11); + assert(t.b); + assert(t.c == 21); + + t.a = 12; + assert(pos == 12); + + const auto &[ca, cb, cc] = t; + t.c = 30; + assert(ca == 12); + assert(cb); + assert(cc == 30); + + assert(sum(t) == 43); + return 0; +} diff --git a/tests/unit/structured_binding_trivial.cpp b/tests/unit/structured_binding_trivial.cpp new file mode 100644 index 000000000..823b0f44b --- /dev/null +++ b/tests/unit/structured_binding_trivial.cpp @@ -0,0 +1,23 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++17 +#include + +struct Pair { + int first; + int second; +}; + +int main() { + auto [in, fun] = Pair{1, 2}; + assert(in == 1); + assert(fun == 2); + + Pair p{10, 20}; + auto [a, b] = p; + a = 11; + b += 1; + assert(a == 11); + assert(b == 21); + assert(p.first == 10); + assert(p.second == 20); + return 0; +} From 0e245e6b528942b65a40e4d85254e0e0610719eb Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Tue, 29 Sep 2026 20:21:44 +0100 Subject: [PATCH 09/21] Update tests --- tests/unit/out/refcount/struct_ctor.rs | 140 +++++++++++++++++++------ tests/unit/out/unsafe/struct_ctor.rs | 6 +- 2 files changed, 110 insertions(+), 36 deletions(-) diff --git a/tests/unit/out/refcount/struct_ctor.rs b/tests/unit/out/refcount/struct_ctor.rs index 2455fc2fe..cf521d728 100644 --- a/tests/unit/out/refcount/struct_ctor.rs +++ b/tests/unit/out/refcount/struct_ctor.rs @@ -6,53 +6,112 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] -#[byte_size(8)] +#[derive(VaArg, FnPtrArg, Default)] pub struct StructWithCtor { - #[offset(0)] - x1_: i32, - #[offset(4)] - x2_: i32, + x1_: Value, + x2_: Value, } impl StructWithCtor { - pub fn new(mut x1: i32, mut x2: i32) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { x1_: x1, x2_: x2 })); + pub fn new(x1: i32, x2: i32) -> Self { + let x1: Value = Rc::new(RefCell::new(x1)); + let x2: Value = Rc::new(RefCell::new(x2)); + let __this: Value = Rc::new(RefCell::new(Self { + x1_: Rc::new(RefCell::new((*x1.borrow()))), + x2_: Rc::new(RefCell::new((*x2.borrow()))), + })); let this: Ptr = __this.as_pointer(); - field!(this, x1_).with_mut(|__v| __v.prefix_inc()); - field!(this, x2_).with_mut(|__v| __v.prefix_dec()); + (*(*this.upgrade().deref()).x1_.borrow_mut()).prefix_inc(); + (*(*this.upgrade().deref()).x2_.borrow_mut()).prefix_dec(); Rc::try_unwrap(__this).ok().unwrap().into_inner() } } +impl Clone for StructWithCtor { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + x1_: Rc::new(RefCell::new((*self.x1_.borrow()))), + x2_: Rc::new(RefCell::new((*self.x2_.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for StructWithCtor { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.x1_.borrow()).to_bytes(&mut buf[0..4]); + (*self.x2_.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + x1_: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + x2_: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} pub fn foo_0(x: Ptr) -> Ptr { return (x).clone(); } -#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] -#[byte_size(4)] +#[derive(VaArg, FnPtrArg, Default)] pub struct Value_ { - #[offset(0)] - pub v: i32, + pub v: Value, } impl Value_ { - pub fn new(mut u: i32) -> Self { - Self { v: u } + 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(Clone, Record, ByteRepr, VaArg, FnPtrArg)] -#[byte_size(8)] +#[derive(VaArg, FnPtrArg)] pub struct Ptr_ { - #[offset(0)] - #[byte_size(4)] - pub v1: Value_, - #[offset(4)] - #[byte_size(4)] - pub v2: Value_, + pub v1: Value, + pub v2: Value, } impl Ptr_ { pub fn new() -> Self { - Self { - v1: Value_::new({ 11 }), - v2: Value_::new({ 22 }), - } + 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_ { @@ -60,6 +119,21 @@ impl Default for Ptr_ { { 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()); @@ -73,9 +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 mut p: Ptr_ = Ptr_::new(); - assert!((p.v1.v == 11)); - assert!((p.v2.v == 22)); + 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 { @@ -84,10 +158,10 @@ pub trait StructWithCtorImpl { } impl StructWithCtorImpl for Ptr { fn x1(&self) -> Ptr { - return field_ptr!((*self), x1_); + return (*(*self).upgrade().deref()).x1_.as_pointer(); } fn x2(&self) -> Ptr { - return field_ptr!((*self), x2_); + return (*(*self).upgrade().deref()).x2_.as_pointer(); } } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/struct_ctor.rs b/tests/unit/out/unsafe/struct_ctor.rs index 8e8b0a792..30a92872a 100644 --- a/tests/unit/out/unsafe/struct_ctor.rs +++ b/tests/unit/out/unsafe/struct_ctor.rs @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] -#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +#[derive(Copy, Clone, VaArg, Default)] pub struct StructWithCtor { x1_: i32, x2_: i32, @@ -30,7 +30,7 @@ pub unsafe fn foo_0(x: *mut i32) -> *mut i32 { return x; } #[repr(C)] -#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] +#[derive(Copy, Clone, VaArg, Default)] pub struct Value_ { pub v: i32, } @@ -41,7 +41,7 @@ impl Value_ { } } #[repr(C)] -#[derive(Copy, Clone, VaArg, FnPtrArg)] +#[derive(Copy, Clone, VaArg)] pub struct Ptr_ { pub v1: Value_, pub v2: Value_, From 1f8056c15f4e439ea1e9046e93a0985a7843ec21 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 10:43:23 +0100 Subject: [PATCH 10/21] Translate decompositions --- cpp2rust/converter/converter.cpp | 6 + cpp2rust/converter/converter_lib.cpp | 7 + .../out/refcount/structured_binding_array.rs | 34 ++++ .../refcount/structured_binding_copy_ctor.rs | 90 ++++++++++ .../structured_binding_element_ctor.rs | 162 ++++++++++++++++++ .../refcount/structured_binding_move_ctor.rs | 161 +++++++++++++++++ .../out/refcount/structured_binding_pair.rs | 51 ++++++ .../refcount/structured_binding_range_for.rs | 79 +++++++++ .../out/refcount/structured_binding_ref.rs | 80 +++++++++ .../refcount/structured_binding_trivial.rs | 63 +++++++ .../out/unsafe/structured_binding_array.rs | 30 ++++ .../unsafe/structured_binding_copy_ctor.rs | 65 +++++++ .../unsafe/structured_binding_element_ctor.rs | 101 +++++++++++ .../unsafe/structured_binding_move_ctor.rs | 91 ++++++++++ .../out/unsafe/structured_binding_pair.rs | 35 ++++ .../unsafe/structured_binding_range_for.rs | 57 ++++++ .../unit/out/unsafe/structured_binding_ref.rs | 49 ++++++ .../out/unsafe/structured_binding_trivial.rs | 41 +++++ 18 files changed, 1202 insertions(+) create mode 100644 tests/unit/out/refcount/structured_binding_array.rs create mode 100644 tests/unit/out/refcount/structured_binding_copy_ctor.rs create mode 100644 tests/unit/out/refcount/structured_binding_element_ctor.rs create mode 100644 tests/unit/out/refcount/structured_binding_move_ctor.rs create mode 100644 tests/unit/out/refcount/structured_binding_pair.rs create mode 100644 tests/unit/out/refcount/structured_binding_range_for.rs create mode 100644 tests/unit/out/refcount/structured_binding_ref.rs create mode 100644 tests/unit/out/refcount/structured_binding_trivial.rs create mode 100644 tests/unit/out/unsafe/structured_binding_array.rs create mode 100644 tests/unit/out/unsafe/structured_binding_copy_ctor.rs create mode 100644 tests/unit/out/unsafe/structured_binding_element_ctor.rs create mode 100644 tests/unit/out/unsafe/structured_binding_move_ctor.rs create mode 100644 tests/unit/out/unsafe/structured_binding_pair.rs create mode 100644 tests/unit/out/unsafe/structured_binding_range_for.rs create mode 100644 tests/unit/out/unsafe/structured_binding_ref.rs create mode 100644 tests/unit/out/unsafe/structured_binding_trivial.rs diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 34e85773d..31b3937f4 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -3273,10 +3273,16 @@ bool Converter::VisitDeclRefExpr(clang::DeclRefExpr *expr) { computed_expr_type_ = ComputedExprType::FreshValue; return false; } + if (auto init = AsLambdaUncapturedConstant(curr_function_, expr)) { Convert(init); return false; } + + if (auto *binding = clang::dyn_cast(expr->getDecl())) { + Convert(binding->getBinding()); + return false; + } ConvertDeclRefValue(expr, expr->getDecl()); return false; } diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index edfdaa46f..f7bd2335e 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -998,6 +998,13 @@ std::string GetNamedDeclAsString(const clang::NamedDecl *decl) { } } + if (clang::isa(decl)) { + return std::format( + "__decomp_{}", + type_mapping.try_emplace(GetID(decl), type_mapping.size()) + .first->second); + } + // Anonymous record or enum if (name.empty() && (clang::isa(decl) || diff --git a/tests/unit/out/refcount/structured_binding_array.rs b/tests/unit/out/refcount/structured_binding_array.rs new file mode 100644 index 000000000..3917de173 --- /dev/null +++ b/tests/unit/out/refcount/structured_binding_array.rs @@ -0,0 +1,34 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let arr: Value> = Rc::new(RefCell::new(Box::new([1, 2, 3]))); + let __decomp_0: Value> = + Rc::new(RefCell::new(Box::new(std::array::from_fn::<_, 3, _>( + |__i: usize| (*arr.borrow())[(__i) as usize], + )))); + (*__decomp_0.borrow_mut())[(0) as usize] = 10; + assert!(((*__decomp_0.borrow())[(0) as usize] == 10)); + assert!(((*__decomp_0.borrow())[(1) as usize] == 2)); + assert!(((*__decomp_0.borrow())[(2) as usize] == 3)); + assert!(((*arr.borrow())[(0) as usize] == 1)); + let __decomp_1: Ptr = (arr.as_pointer() as Ptr); + (__decomp_1).offset((0) as isize).write(7); + { + let _ptr = (__decomp_1).offset((2) as isize); + _ptr.write(_ptr.read() + ((__decomp_1).offset((1) as isize).read())) + }; + assert!(((*arr.borrow())[(0) as usize] == 7)); + assert!(((*arr.borrow())[(2) as usize] == 5)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_copy_ctor.rs b/tests/unit/out/refcount/structured_binding_copy_ctor.rs new file mode 100644 index 000000000..c71bcef66 --- /dev/null +++ b/tests/unit/out/refcount/structured_binding_copy_ctor.rs @@ -0,0 +1,90 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +thread_local!( + pub static copies_0: Value = Rc::new(RefCell::new(0)); +); +#[derive(VaArg, FnPtrArg, Default)] +pub struct Counted { + pub x: Value, + pub y: Value, +} +impl Counted { + pub fn new(x: i32, y: i32) -> Self { + let x: Value = Rc::new(RefCell::new(x)); + let y: Value = Rc::new(RefCell::new(y)); + let __this: Value = Rc::new(RefCell::new(Self { + x: Rc::new(RefCell::new((*x.borrow()))), + y: Rc::new(RefCell::new((*y.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } + pub fn copy_from(other: Ptr) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + x: Rc::new(RefCell::new(((*(*other.upgrade().deref()).x.borrow()) * 2))), + y: Rc::new(RefCell::new(((*(*other.upgrade().deref()).y.borrow()) * 2))), + })); + let this: Ptr = __this.as_pointer(); + (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl Clone for Counted { + fn clone(&self) -> Self { + let __src: Value = Rc::new(RefCell::new(Counted { + x: self.x.clone(), + y: self.y.clone(), + })); + Counted::copy_from(__src.as_pointer()) + } +} +impl ByteRepr for Counted { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.x.borrow()).to_bytes(&mut buf[0..4]); + (*self.y.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + x: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + y: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} +pub fn make_counted_1() -> Counted { + return Counted::new({ 5 }, { 6 }); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let s: Value = Rc::new(RefCell::new(Counted::new({ 1 }, { 2 }))); + let __decomp_2: Value = Rc::new(RefCell::new(Counted::copy_from({ s.as_pointer() }))); + assert!((copies_0.with(|rc| *rc.borrow()) == 1)); + assert!(((*(*__decomp_2.borrow()).x.borrow()) == 2)); + assert!(((*(*__decomp_2.borrow()).y.borrow()) == 4)); + let __decomp_3: Ptr = s.as_pointer(); + assert!((copies_0.with(|rc| *rc.borrow()) == 1)); + assert!(((*(*__decomp_3.upgrade().deref()).x.borrow()) == 1)); + assert!(((*(*__decomp_3.upgrade().deref()).y.borrow()) == 2)); + let __decomp_4: Ptr = s.as_pointer(); + assert!((copies_0.with(|rc| *rc.borrow()) == 1)); + assert!(((*(*__decomp_4.upgrade().deref()).x.borrow()) == 1)); + let __decomp_5: Value = Rc::new(RefCell::new(({ make_counted_1() }))); + assert!((copies_0.with(|rc| *rc.borrow()) == 1)); + assert!(((*(*__decomp_5.borrow()).x.borrow()) == 5)); + assert!(((*(*__decomp_5.borrow()).y.borrow()) == 6)); + return 0; +} +pub fn __cpp2rust_init_globals() { + let _ = copies_0.with(|_| ()); +} diff --git a/tests/unit/out/refcount/structured_binding_element_ctor.rs b/tests/unit/out/refcount/structured_binding_element_ctor.rs new file mode 100644 index 000000000..1d4d41ae8 --- /dev/null +++ b/tests/unit/out/refcount/structured_binding_element_ctor.rs @@ -0,0 +1,162 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +thread_local!( + pub static copies_0: Value = Rc::new(RefCell::new(0)); +); +thread_local!( + pub static moves_1: Value = Rc::new(RefCell::new(0)); +); +#[derive(VaArg, FnPtrArg, Default)] +pub struct Elem { + pub v: Value, +} +impl Elem { + pub fn new(v: i32) -> Self { + let v: Value = Rc::new(RefCell::new(v)); + let __this: Value = Rc::new(RefCell::new(Self { + v: Rc::new(RefCell::new((*v.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } + pub fn copy_from(other: Ptr) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + v: Rc::new(RefCell::new( + ((*(*other.upgrade().deref()).v.borrow()) + 100), + )), + })); + let this: Ptr = __this.as_pointer(); + (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } + pub fn move_from(other: Ptr) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + v: Rc::new(RefCell::new( + ((*(*other.upgrade().deref()).v.borrow()) + 1000), + )), + })); + let this: Ptr = __this.as_pointer(); + (*(*other.upgrade().deref()).v.borrow_mut()) = -1_i32; + (*moves_1.with(Value::clone).borrow_mut()).prefix_inc(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl Clone for Elem { + fn clone(&self) -> Self { + let __src: Value = Rc::new(RefCell::new(Elem { v: self.v.clone() })); + Elem::copy_from(__src.as_pointer()) + } +} +impl ByteRepr for Elem { + 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(VaArg, FnPtrArg, Default)] +pub struct Two { + pub a: Value, + pub b: Value, +} +impl Clone for Two { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + a: Rc::new(RefCell::new(Elem::copy_from({ self.a.as_pointer() }))), + b: Rc::new(RefCell::new(Elem::copy_from({ self.b.as_pointer() }))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for Two { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.a.borrow()).to_bytes(&mut buf[0..4]); + (*self.b.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + a: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + b: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} +pub fn make_two_2() -> Two { + return Two { + a: Rc::new(RefCell::new(Elem::new({ 1 }))), + b: Rc::new(RefCell::new(Elem::new({ 2 }))), + }; +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let t: Value = Rc::new(RefCell::new(Two { + a: Rc::new(RefCell::new(Elem::new({ 1 }))), + b: Rc::new(RefCell::new(Elem::new({ 2 }))), + })); + let base_copies: Value = Rc::new(RefCell::new(copies_0.with(|rc| *rc.borrow()))); + let base_moves: Value = Rc::new(RefCell::new(moves_1.with(|rc| *rc.borrow()))); + let __decomp_3: Value = Rc::new(RefCell::new((*t.borrow()).clone())); + assert!((copies_0.with(|rc| *rc.borrow()) == ((*base_copies.borrow()) + 2))); + assert!((moves_1.with(|rc| *rc.borrow()) == (*base_moves.borrow()))); + assert!(((*(*(*__decomp_3.borrow()).a.borrow()).v.borrow()) == 101)); + assert!(((*(*(*__decomp_3.borrow()).b.borrow()).v.borrow()) == 102)); + let __decomp_4: Ptr = t.as_pointer(); + assert!((copies_0.with(|rc| *rc.borrow()) == ((*base_copies.borrow()) + 2))); + assert!(((*(*(*__decomp_4.upgrade().deref()).a.borrow()).v.borrow()) == 1)); + (*(*(*__decomp_4.upgrade().deref()).a.borrow()).v.borrow_mut()) = 50; + assert!(((*(*(*t.borrow()).a.borrow()).v.borrow()) == 50)); + let __decomp_5: Value = Rc::new(RefCell::new((*t.borrow()).clone())); + assert!((moves_1.with(|rc| *rc.borrow()) == ((*base_moves.borrow()) + 2))); + assert!(((*(*(*__decomp_5.borrow()).a.borrow()).v.borrow()) == 1050)); + assert!(((*(*(*__decomp_5.borrow()).b.borrow()).v.borrow()) == 1002)); + assert!(((*(*(*t.borrow()).a.borrow()).v.borrow()) == -1_i32)); + let before_copies: Value = Rc::new(RefCell::new(copies_0.with(|rc| *rc.borrow()))); + let before_moves: Value = Rc::new(RefCell::new(moves_1.with(|rc| *rc.borrow()))); + let __decomp_6: Value = Rc::new(RefCell::new(({ make_two_2() }))); + assert!((copies_0.with(|rc| *rc.borrow()) == (*before_copies.borrow()))); + assert!((moves_1.with(|rc| *rc.borrow()) == (*before_moves.borrow()))); + assert!(((*(*(*__decomp_6.borrow()).a.borrow()).v.borrow()) == 1)); + let p: Value<(Value, Value)> = Rc::new(RefCell::new(( + Rc::new(RefCell::new( + Elem::new({ 7 }).try_into().expect("failed conversion"), + )), + Rc::new(RefCell::new( + Elem::new({ 8 }).try_into().expect("failed conversion"), + )), + ))); + (*before_copies.borrow_mut()) = copies_0.with(|rc| *rc.borrow()); + let __decomp_7: Value<(Value, Value)> = Rc::new(RefCell::new(( + Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), + Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), + ))); + assert!((copies_0.with(|rc| *rc.borrow()) == ((*before_copies.borrow()) + 2))); + assert!( + ((*(*x.upgrade().deref()).v.borrow()) == ((*(*(*p.borrow()).0.borrow()).v.borrow()) + 100)) + ); + assert!( + ((*(*y.upgrade().deref()).v.borrow()) == ((*(*(*p.borrow()).1.borrow()).v.borrow()) + 100)) + ); + return 0; +} +pub fn __cpp2rust_init_globals() { + let _ = copies_0.with(|_| ()); + let _ = moves_1.with(|_| ()); +} diff --git a/tests/unit/out/refcount/structured_binding_move_ctor.rs b/tests/unit/out/refcount/structured_binding_move_ctor.rs new file mode 100644 index 000000000..9e7e07869 --- /dev/null +++ b/tests/unit/out/refcount/structured_binding_move_ctor.rs @@ -0,0 +1,161 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +thread_local!( + pub static copies_0: Value = Rc::new(RefCell::new(0)); +); +thread_local!( + pub static moves_1: Value = Rc::new(RefCell::new(0)); +); +#[derive(VaArg, FnPtrArg, Default)] +pub struct Movable { + pub x: Value, + pub y: Value, +} +impl Movable { + pub fn new(x: i32, y: i32) -> Self { + let x: Value = Rc::new(RefCell::new(x)); + let y: Value = Rc::new(RefCell::new(y)); + let __this: Value = Rc::new(RefCell::new(Self { + x: Rc::new(RefCell::new((*x.borrow()))), + y: Rc::new(RefCell::new((*y.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } + pub fn copy_from(other: Ptr) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + x: Rc::new(RefCell::new((*(*other.upgrade().deref()).x.borrow()))), + y: Rc::new(RefCell::new((*(*other.upgrade().deref()).y.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } + pub fn move_from(other: Ptr) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + x: Rc::new(RefCell::new((*(*other.upgrade().deref()).x.borrow()))), + y: Rc::new(RefCell::new((*(*other.upgrade().deref()).y.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + (*(*other.upgrade().deref()).x.borrow_mut()) = 0; + (*(*other.upgrade().deref()).y.borrow_mut()) = 0; + (*moves_1.with(Value::clone).borrow_mut()).prefix_inc(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl Clone for Movable { + fn clone(&self) -> Self { + let __src: Value = Rc::new(RefCell::new(Movable { + x: self.x.clone(), + y: self.y.clone(), + })); + Movable::copy_from(__src.as_pointer()) + } +} +impl ByteRepr for Movable { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.x.borrow()).to_bytes(&mut buf[0..4]); + (*self.y.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + x: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + y: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} +#[derive(VaArg, FnPtrArg, Default)] +pub struct Holder { + pub xs: Value>, + pub ys: Value>, +} +impl Clone for Holder { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + xs: Rc::new(RefCell::new((*self.xs.borrow()).clone())), + ys: Rc::new(RefCell::new((*self.ys.borrow()).clone())), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for Holder { + fn byte_size() -> usize { + 48 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.xs.borrow()).to_bytes(&mut buf[0..24]); + (*self.ys.borrow()).to_bytes(&mut buf[24..48]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + xs: Rc::new(RefCell::new(>::from_bytes(&buf[0..24]))), + ys: Rc::new(RefCell::new(>::from_bytes(&buf[24..48]))), + } + } +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let m: Value = Rc::new(RefCell::new(Movable::new({ 3 }, { 4 }))); + let __decomp_2: Value = Rc::new(RefCell::new(Movable::move_from({ m.as_pointer() }))); + assert!((moves_1.with(|rc| *rc.borrow()) == 1)); + assert!((copies_0.with(|rc| *rc.borrow()) == 0)); + assert!(((*(*__decomp_2.borrow()).x.borrow()) == 3)); + assert!(((*(*__decomp_2.borrow()).y.borrow()) == 4)); + assert!(((*(*m.borrow()).x.borrow()) == 0)); + assert!(((*(*m.borrow()).y.borrow()) == 0)); + let h: Value = Rc::new(RefCell::new(Holder { + xs: Rc::new(RefCell::new(vec![1, 2, 3])), + ys: Rc::new(RefCell::new(vec![4, 5])), + })); + let __decomp_3: Value = + Rc::new(RefCell::new(({ HolderImpl::extract(&h.as_pointer()) }))); + assert!(((*(*__decomp_3.borrow()).xs.borrow()).len() == 3_usize)); + assert!(((*(*__decomp_3.borrow()).ys.borrow()).len() == 2_usize)); + assert!( + ((((*__decomp_3.borrow()).xs.as_pointer() as Ptr) + .offset(2_usize) + .read()) + == 3) + ); + assert!( + ((((*__decomp_3.borrow()).ys.as_pointer() as Ptr) + .offset(0_usize) + .read()) + == 4) + ); + assert!((*(*h.borrow()).xs.borrow()).is_empty()); + assert!((*(*h.borrow()).ys.borrow()).is_empty()); + return 0; +} +pub trait HolderImpl { + fn extract(&self) -> Holder; +} +impl HolderImpl for Ptr { + fn extract(&self) -> Holder { + return Holder { + xs: Rc::new(RefCell::new(std::mem::take( + &mut (*(*(*self).upgrade().deref()).xs.borrow_mut()), + ))), + ys: Rc::new(RefCell::new(std::mem::take( + &mut (*(*(*self).upgrade().deref()).ys.borrow_mut()), + ))), + }; + } +} +pub fn __cpp2rust_init_globals() { + let _ = copies_0.with(|_| ()); + let _ = moves_1.with(|_| ()); +} diff --git a/tests/unit/out/refcount/structured_binding_pair.rs b/tests/unit/out/refcount/structured_binding_pair.rs new file mode 100644 index 000000000..b9c3e0278 --- /dev/null +++ b/tests/unit/out/refcount/structured_binding_pair.rs @@ -0,0 +1,51 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn make_std_pair_0(x: i32) -> (Value, Value) { + let x: Value = Rc::new(RefCell::new(x)); + return ( + Rc::new(RefCell::new( + (*x.borrow()).try_into().expect("failed conversion"), + )), + Rc::new(RefCell::new( + ((*x.borrow()) > 0).try_into().expect("failed conversion"), + )), + ); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let __decomp_1: Value<(Value, Value)> = + Rc::new(RefCell::new(({ make_std_pair_0(5) }))); + assert!(((value.read()) == 5)); + assert!(((positive.read()) as bool)); + let p: Value<(Value, Value)> = Rc::new(RefCell::new(( + Rc::new(RefCell::new(1.try_into().expect("failed conversion"))), + Rc::new(RefCell::new(2.try_into().expect("failed conversion"))), + ))); + let __decomp_2: Value<(Value, Value)> = Rc::new(RefCell::new(( + Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), + Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), + ))); + a.write(10); + assert!(((a.read()) == 10)); + assert!(((b.read()) == 2)); + assert!(((*(*p.borrow()).0.borrow()) == 1)); + let __decomp_3: Ptr<(Value, Value)> = p.as_pointer(); + x.write(3); + { + let _ptr = y.clone(); + _ptr.write(_ptr.read() + 4) + }; + assert!(((*(*p.borrow()).0.borrow()) == 3)); + assert!(((*(*p.borrow()).1.borrow()) == 6)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_range_for.rs b/tests/unit/out/refcount/structured_binding_range_for.rs new file mode 100644 index 000000000..90bcbe0dc --- /dev/null +++ b/tests/unit/out/refcount/structured_binding_range_for.rs @@ -0,0 +1,79 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(VaArg, FnPtrArg, Default)] +pub struct Pair { + pub first: Value, + pub second: Value, +} +impl Clone for Pair { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + first: Rc::new(RefCell::new((*self.first.borrow()))), + second: Rc::new(RefCell::new((*self.second.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for Pair { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.first.borrow()).to_bytes(&mut buf[0..4]); + (*self.second.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + first: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + second: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let arr: Value> = Rc::new(RefCell::new(Box::new([ + Pair { + first: Rc::new(RefCell::new(1)), + second: Rc::new(RefCell::new(2)), + }, + Pair { + first: Rc::new(RefCell::new(3)), + second: Rc::new(RefCell::new(4)), + }, + Pair { + first: Rc::new(RefCell::new(5)), + second: Rc::new(RefCell::new(6)), + }, + ]))); + 'loop_: for mut __decomp_0 in arr.as_pointer() as Ptr { + (*(*__decomp_0.upgrade().deref()).first.borrow_mut()) += + (*(*__decomp_0.upgrade().deref()).second.borrow()); + } + assert!(((*(*arr.borrow())[(0) as usize].first.borrow()) == 3)); + assert!(((*(*arr.borrow())[(2) as usize].first.borrow()) == 11)); + 'loop_: for mut __decomp_1 in arr.as_pointer() as Ptr { + let __decomp_1: Value = Rc::new(RefCell::new(__decomp_1.upgrade().deref().clone())); + (*(*__decomp_1.borrow()).first.borrow_mut()) = 0; + (*(*__decomp_1.borrow()).second.borrow_mut()) = 0; + } + assert!(((*(*arr.borrow())[(1) as usize].first.borrow()) == 7)); + assert!(((*(*arr.borrow())[(1) as usize].second.borrow()) == 4)); + let sum: Value = Rc::new(RefCell::new(0)); + 'loop_: for mut __decomp_2 in arr.as_pointer() as Ptr { + (*sum.borrow_mut()) += ((*(*__decomp_2.upgrade().deref()).first.borrow()) + * (*(*__decomp_2.upgrade().deref()).second.borrow())); + } + assert!(((*sum.borrow()) == (((3 * 2) + (7 * 4)) + (11 * 6)))); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_ref.rs b/tests/unit/out/refcount/structured_binding_ref.rs new file mode 100644 index 000000000..48c3003b6 --- /dev/null +++ b/tests/unit/out/refcount/structured_binding_ref.rs @@ -0,0 +1,80 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(VaArg, FnPtrArg, Default)] +pub struct Triple { + pub a: Value, + pub b: Value, + pub c: Value, +} +impl Clone for Triple { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + a: Rc::new(RefCell::new((*self.a.borrow()))), + b: Rc::new(RefCell::new((*self.b.borrow()))), + c: Rc::new(RefCell::new((*self.c.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for Triple { + fn byte_size() -> usize { + 12 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.a.borrow()).to_bytes(&mut buf[0..4]); + (*self.b.borrow()).to_bytes(&mut buf[4..5]); + (*self.c.borrow()).to_bytes(&mut buf[8..12]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + a: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + b: Rc::new(RefCell::new(::from_bytes(&buf[4..5]))), + c: Rc::new(RefCell::new(::from_bytes(&buf[8..12]))), + } + } +} +pub fn sum_0(t: Ptr) -> i32 { + let __decomp_1: Ptr = (t).clone(); + return (((*(*__decomp_1.upgrade().deref()).a.borrow()) + + (if (*(*__decomp_1.upgrade().deref()).b.borrow()) { + 1 + } else { + 0 + })) + + (*(*__decomp_1.upgrade().deref()).c.borrow())); +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let t: Value = Rc::new(RefCell::new(Triple { + a: Rc::new(RefCell::new(10)), + b: Rc::new(RefCell::new(false)), + c: Rc::new(RefCell::new(20)), + })); + let __decomp_2: Ptr = t.as_pointer(); + (*(*__decomp_2.upgrade().deref()).a.borrow_mut()) = 11; + (*(*__decomp_2.upgrade().deref()).b.borrow_mut()) = true; + (*(*__decomp_2.upgrade().deref()).c.borrow_mut()) += 1; + assert!(((*(*t.borrow()).a.borrow()) == 11)); + assert!((*(*t.borrow()).b.borrow())); + assert!(((*(*t.borrow()).c.borrow()) == 21)); + (*(*t.borrow()).a.borrow_mut()) = 12; + assert!(((*(*__decomp_2.upgrade().deref()).a.borrow()) == 12)); + let __decomp_3: Ptr = t.as_pointer(); + (*(*t.borrow()).c.borrow_mut()) = 30; + assert!(((*(*__decomp_3.upgrade().deref()).a.borrow()) == 12)); + assert!((*(*__decomp_3.upgrade().deref()).b.borrow())); + assert!(((*(*__decomp_3.upgrade().deref()).c.borrow()) == 30)); + assert!((({ sum_0(t.as_pointer(),) }) == 43)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_trivial.rs b/tests/unit/out/refcount/structured_binding_trivial.rs new file mode 100644 index 000000000..03e0572ec --- /dev/null +++ b/tests/unit/out/refcount/structured_binding_trivial.rs @@ -0,0 +1,63 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(VaArg, FnPtrArg, Default)] +pub struct Pair { + pub first: Value, + pub second: Value, +} +impl Clone for Pair { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + first: Rc::new(RefCell::new((*self.first.borrow()))), + second: Rc::new(RefCell::new((*self.second.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for Pair { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.first.borrow()).to_bytes(&mut buf[0..4]); + (*self.second.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + first: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + second: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} +pub fn main() { + __cpp2rust_init_globals(); + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let __decomp_0: Value = Rc::new(RefCell::new(Pair { + first: Rc::new(RefCell::new(1)), + second: Rc::new(RefCell::new(2)), + })); + assert!(((*(*__decomp_0.borrow()).first.borrow()) == 1)); + assert!(((*(*__decomp_0.borrow()).second.borrow()) == 2)); + let p: Value = Rc::new(RefCell::new(Pair { + first: Rc::new(RefCell::new(10)), + second: Rc::new(RefCell::new(20)), + })); + let __decomp_1: Value = Rc::new(RefCell::new((*p.borrow()).clone())); + (*(*__decomp_1.borrow()).first.borrow_mut()) = 11; + (*(*__decomp_1.borrow()).second.borrow_mut()) += 1; + assert!(((*(*__decomp_1.borrow()).first.borrow()) == 11)); + assert!(((*(*__decomp_1.borrow()).second.borrow()) == 21)); + assert!(((*(*p.borrow()).first.borrow()) == 10)); + assert!(((*(*p.borrow()).second.borrow()) == 20)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/structured_binding_array.rs b/tests/unit/out/unsafe/structured_binding_array.rs new file mode 100644 index 000000000..1bbfef98c --- /dev/null +++ b/tests/unit/out/unsafe/structured_binding_array.rs @@ -0,0 +1,30 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut arr: [i32; 3] = [1, 2, 3]; + let mut __decomp_0: [i32; 3] = std::array::from_fn::<_, 3, _>(|__i: usize| arr[(__i)]); + __decomp_0[(0) as usize] = 10; + assert!(((__decomp_0[(0) as usize]) == (10))); + assert!(((__decomp_0[(1) as usize]) == (2))); + assert!(((__decomp_0[(2) as usize]) == (3))); + assert!(((arr[(0) as usize]) == (1))); + let __decomp_1: *mut [i32; 3] = &mut arr; + (*__decomp_1)[(0) as usize] = 7; + (*__decomp_1)[(2) as usize] += (*__decomp_1)[(1) as usize]; + assert!(((arr[(0) as usize]) == (7))); + assert!(((arr[(2) as usize]) == (5))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/structured_binding_copy_ctor.rs b/tests/unit/out/unsafe/structured_binding_copy_ctor.rs new file mode 100644 index 000000000..db490f085 --- /dev/null +++ b/tests/unit/out/unsafe/structured_binding_copy_ctor.rs @@ -0,0 +1,65 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub static mut copies_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +#[repr(C)] +#[derive(VaArg, Default)] +pub struct Counted { + pub x: i32, + pub y: i32, +} +impl Counted { + pub unsafe fn new(mut x: i32, mut y: i32) -> Self { + let mut this = Self { x: x, y: y }; + this + } + pub unsafe fn copy_from(other: *const Counted) -> Self { + let mut this = Self { + x: (((*other).x) * (2)), + y: (((*other).y) * (2)), + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)).prefix_inc(); + this + } +} +impl Clone for Counted { + fn clone(&self) -> Self { + unsafe { Counted::copy_from(self as *const Counted) } + } +} +pub unsafe fn make_counted_1() -> Counted { + return Counted::new({ 5 }, { 6 }); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut s: Counted = Counted::new({ 1 }, { 2 }); + let mut __decomp_2: Counted = Counted::copy_from({ &s }); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == (1))); + assert!(((__decomp_2.x) == (2))); + assert!(((__decomp_2.y) == (4))); + let __decomp_3: *mut Counted = &mut s; + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == (1))); + assert!((((*__decomp_3).x) == (1))); + assert!((((*__decomp_3).y) == (2))); + let __decomp_4: *const Counted = &s; + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == (1))); + assert!((((*__decomp_4).x) == (1))); + let mut __decomp_5: Counted = (unsafe { make_counted_1() }); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == (1))); + assert!(((__decomp_5.x) == (5))); + assert!(((__decomp_5.y) == (6))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() { + std::cell::LazyCell::force(&*&raw const copies_0); +} diff --git a/tests/unit/out/unsafe/structured_binding_element_ctor.rs b/tests/unit/out/unsafe/structured_binding_element_ctor.rs new file mode 100644 index 000000000..e7ee9217d --- /dev/null +++ b/tests/unit/out/unsafe/structured_binding_element_ctor.rs @@ -0,0 +1,101 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub static mut copies_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +pub static mut moves_1: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +#[repr(C)] +#[derive(VaArg, Default)] +pub struct Elem { + pub v: i32, +} +impl Elem { + pub unsafe fn new(mut v: i32) -> Self { + let mut this = Self { v: v }; + this + } + pub unsafe fn copy_from(other: *const Elem) -> Self { + let mut this = Self { + v: (((*other).v) + (100)), + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)).prefix_inc(); + this + } + pub unsafe fn move_from(other: *mut Elem) -> Self { + let mut this = Self { + v: (((*other).v) + (1000)), + }; + (*other).v = -1_i32; + (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)).prefix_inc(); + this + } +} +impl Clone for Elem { + fn clone(&self) -> Self { + unsafe { Elem::copy_from(self as *const Elem) } + } +} +#[repr(C)] +#[derive(Clone, VaArg, Default)] +pub struct Two { + pub a: Elem, + pub b: Elem, +} +pub unsafe fn make_two_2() -> Two { + return Two { + a: Elem::new({ 1 }), + b: Elem::new({ 2 }), + }; +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut t: Two = Two { + a: Elem::new({ 1 }), + b: Elem::new({ 2 }), + }; + let mut base_copies: i32 = (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)); + let mut base_moves: i32 = (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)); + let mut __decomp_3: Two = t.clone(); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == ((base_copies) + (2)))); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)) == (base_moves))); + assert!(((__decomp_3.a.v) == (101))); + assert!(((__decomp_3.b.v) == (102))); + let __decomp_4: *mut Two = &mut t; + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == ((base_copies) + (2)))); + assert!((((*__decomp_4).a.v) == (1))); + (*__decomp_4).a.v = 50; + assert!(((t.a.v) == (50))); + let mut __decomp_5: Two = t.clone(); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)) == ((base_moves) + (2)))); + assert!(((__decomp_5.a.v) == (1050))); + assert!(((__decomp_5.b.v) == (1002))); + assert!(((t.a.v) == (-1_i32))); + let mut before_copies: i32 = (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)); + let mut before_moves: i32 = (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)); + let mut __decomp_6: Two = (unsafe { make_two_2() }); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == (before_copies))); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)) == (before_moves))); + assert!(((__decomp_6.a.v) == (1))); + let mut p: (Elem, Elem) = (Elem::new({ 7 }).into(), Elem::new({ 8 }).into()); + before_copies = (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)); + let mut __decomp_7: (Elem, Elem) = p.clone(); + assert!( + ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == ((before_copies) + (2))) + ); + assert!((((*x).v) == ((p.0.v) + (100)))); + assert!((((*y).v) == ((p.1.v) + (100)))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() { + std::cell::LazyCell::force(&*&raw const copies_0); + std::cell::LazyCell::force(&*&raw const moves_1); +} diff --git a/tests/unit/out/unsafe/structured_binding_move_ctor.rs b/tests/unit/out/unsafe/structured_binding_move_ctor.rs new file mode 100644 index 000000000..cf062bccb --- /dev/null +++ b/tests/unit/out/unsafe/structured_binding_move_ctor.rs @@ -0,0 +1,91 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub static mut copies_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +pub static mut moves_1: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); +#[repr(C)] +#[derive(VaArg, Default)] +pub struct Movable { + pub x: i32, + pub y: i32, +} +impl Movable { + pub unsafe fn new(mut x: i32, mut y: i32) -> Self { + let mut this = Self { x: x, y: y }; + this + } + pub unsafe fn copy_from(other: *const Movable) -> Self { + let mut this = Self { + x: (*other).x, + y: (*other).y, + }; + (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)).prefix_inc(); + this + } + pub unsafe fn move_from(other: *mut Movable) -> Self { + let mut this = Self { + x: (*other).x, + y: (*other).y, + }; + (*other).x = 0; + (*other).y = 0; + (*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)).prefix_inc(); + this + } +} +impl Clone for Movable { + fn clone(&self) -> Self { + unsafe { Movable::copy_from(self as *const Movable) } + } +} +#[repr(C)] +#[derive(Clone, VaArg, Default)] +pub struct Holder { + pub xs: Vec, + pub ys: Vec, +} +impl Holder { + pub unsafe fn extract(&mut self) -> Holder { + return Holder { + xs: std::mem::take(&mut self.xs), + ys: std::mem::take(&mut self.ys), + }; + } +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut m: Movable = Movable::new({ 3 }, { 4 }); + let mut __decomp_2: Movable = Movable::move_from({ &mut m }); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)) == (1))); + assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == (0))); + assert!(((__decomp_2.x) == (3))); + assert!(((__decomp_2.y) == (4))); + assert!(((m.x) == (0))); + assert!(((m.y) == (0))); + let mut h: Holder = Holder { + xs: vec![1, 2, 3], + ys: vec![4, 5], + }; + let mut __decomp_3: Holder = (unsafe { Holder::extract(&mut h) }); + assert!(((__decomp_3.xs.len()) == (3_usize))); + assert!(((__decomp_3.ys.len()) == (2_usize))); + assert!(((__decomp_3.xs[(2_usize)]) == (3))); + assert!(((__decomp_3.ys[(0_usize)]) == (4))); + assert!(h.xs.is_empty()); + assert!(h.ys.is_empty()); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() { + std::cell::LazyCell::force(&*&raw const copies_0); + std::cell::LazyCell::force(&*&raw const moves_1); +} diff --git a/tests/unit/out/unsafe/structured_binding_pair.rs b/tests/unit/out/unsafe/structured_binding_pair.rs new file mode 100644 index 000000000..3436d1671 --- /dev/null +++ b/tests/unit/out/unsafe/structured_binding_pair.rs @@ -0,0 +1,35 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub unsafe fn make_std_pair_0(mut x: i32) -> (i32, bool) { + return (x.into(), ((x) > (0)).into()); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut __decomp_1: (i32, bool) = (unsafe { make_std_pair_0(5) }); + assert!(((*value) == (5))); + assert!(((*positive) as bool)); + let mut p: (i32, i32) = (1.into(), 2.into()); + let mut __decomp_2: (i32, i32) = p.clone(); + (*a) = 10; + assert!(((*a) == (10))); + assert!(((*b) == (2))); + assert!(((p.0) == (1))); + let __decomp_3: *mut (i32, i32) = &mut p; + (*x) = 3; + (*y) += 4; + assert!(((p.0) == (3))); + assert!(((p.1) == (6))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/structured_binding_range_for.rs b/tests/unit/out/unsafe/structured_binding_range_for.rs new file mode 100644 index 000000000..b6171ace0 --- /dev/null +++ b/tests/unit/out/unsafe/structured_binding_range_for.rs @@ -0,0 +1,57 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, VaArg, Default)] +pub struct Pair { + pub first: i32, + pub second: i32, +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut arr: [Pair; 3] = [ + Pair { + first: 1, + second: 2, + }, + Pair { + first: 3, + second: 4, + }, + Pair { + first: 5, + second: 6, + }, + ]; + 'loop_: for __decomp_0 in 0..(arr.len()) { + let mut __decomp_0 = arr.as_mut_ptr().add(__decomp_0); + (*__decomp_0).first += (*__decomp_0).second; + } + assert!(((arr[(0) as usize].first) == (3))); + assert!(((arr[(2) as usize].first) == (11))); + 'loop_: for __decomp_1 in 0..(arr.len()) { + let mut __decomp_1 = arr[__decomp_1].clone(); + __decomp_1.first = 0; + __decomp_1.second = 0; + } + assert!(((arr[(1) as usize].first) == (7))); + assert!(((arr[(1) as usize].second) == (4))); + let mut sum: i32 = 0; + 'loop_: for __decomp_2 in 0..(arr.len()) { + let mut __decomp_2 = arr.as_ptr().add(__decomp_2); + sum += (((*__decomp_2).first) * ((*__decomp_2).second)); + } + assert!(((sum) == ((((3) * (2)) + ((7) * (4))) + ((11) * (6))))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/structured_binding_ref.rs b/tests/unit/out/unsafe/structured_binding_ref.rs new file mode 100644 index 000000000..f6b62d73c --- /dev/null +++ b/tests/unit/out/unsafe/structured_binding_ref.rs @@ -0,0 +1,49 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, VaArg, Default)] +pub struct Triple { + pub a: i32, + pub b: bool, + pub c: i32, +} +pub unsafe fn sum_0(t: *const Triple) -> i32 { + let __decomp_1: *const Triple = t; + return ((((*__decomp_1).a) + (if (*__decomp_1).b { 1 } else { 0 })) + ((*__decomp_1).c)); +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut t: Triple = Triple { + a: 10, + b: false, + c: 20, + }; + let __decomp_2: *mut Triple = &mut t; + (*__decomp_2).a = 11; + (*__decomp_2).b = true; + (*__decomp_2).c += 1; + assert!(((t.a) == (11))); + assert!(t.b); + assert!(((t.c) == (21))); + t.a = 12; + assert!((((*__decomp_2).a) == (12))); + let __decomp_3: *const Triple = &t; + t.c = 30; + assert!((((*__decomp_3).a) == (12))); + assert!((*__decomp_3).b); + assert!((((*__decomp_3).c) == (30))); + assert!(((unsafe { sum_0(&t,) }) == (43))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/structured_binding_trivial.rs b/tests/unit/out/unsafe/structured_binding_trivial.rs new file mode 100644 index 000000000..70268c1b2 --- /dev/null +++ b/tests/unit/out/unsafe/structured_binding_trivial.rs @@ -0,0 +1,41 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, VaArg, Default)] +pub struct Pair { + pub first: i32, + pub second: i32, +} +pub fn main() { + unsafe { + __cpp2rust_init_globals(); + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut __decomp_0: Pair = Pair { + first: 1, + second: 2, + }; + assert!(((__decomp_0.first) == (1))); + assert!(((__decomp_0.second) == (2))); + let mut p: Pair = Pair { + first: 10, + second: 20, + }; + let mut __decomp_1: Pair = p; + __decomp_1.first = 11; + __decomp_1.second += 1; + assert!(((__decomp_1.first) == (11))); + assert!(((__decomp_1.second) == (21))); + assert!(((p.first) == (10))); + assert!(((p.second) == (20))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} From 23ad73a396f572035ff282625addfba524014bee Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 10:47:05 +0100 Subject: [PATCH 11/21] Update tests --- tests/unit/out/refcount/struct_ctor.rs | 140 ++++------------ .../out/refcount/structured_binding_array.rs | 23 ++- .../refcount/structured_binding_copy_ctor.rs | 64 +++----- .../structured_binding_element_ctor.rs | 152 ++++++------------ .../refcount/structured_binding_move_ctor.rs | 132 +++++---------- .../out/refcount/structured_binding_pair.rs | 14 +- .../refcount/structured_binding_range_for.rs | 73 +++------ .../out/refcount/structured_binding_ref.rs | 81 ++++------ .../refcount/structured_binding_trivial.rs | 68 +++----- tests/unit/out/unsafe/struct_ctor.rs | 6 +- .../unsafe/structured_binding_copy_ctor.rs | 2 +- .../unsafe/structured_binding_element_ctor.rs | 4 +- .../unsafe/structured_binding_move_ctor.rs | 4 +- .../unsafe/structured_binding_range_for.rs | 2 +- .../unit/out/unsafe/structured_binding_ref.rs | 2 +- .../out/unsafe/structured_binding_trivial.rs | 2 +- 16 files changed, 250 insertions(+), 519 deletions(-) diff --git a/tests/unit/out/refcount/struct_ctor.rs b/tests/unit/out/refcount/struct_ctor.rs index cf521d728..2455fc2fe 100644 --- a/tests/unit/out/refcount/struct_ctor.rs +++ b/tests/unit/out/refcount/struct_ctor.rs @@ -6,112 +6,53 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -#[derive(VaArg, FnPtrArg, Default)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(8)] pub struct StructWithCtor { - x1_: Value, - x2_: Value, + #[offset(0)] + x1_: i32, + #[offset(4)] + x2_: i32, } impl StructWithCtor { - pub fn new(x1: i32, x2: i32) -> Self { - let x1: Value = Rc::new(RefCell::new(x1)); - let x2: Value = Rc::new(RefCell::new(x2)); - let __this: Value = Rc::new(RefCell::new(Self { - x1_: Rc::new(RefCell::new((*x1.borrow()))), - x2_: Rc::new(RefCell::new((*x2.borrow()))), - })); + pub fn new(mut x1: i32, mut x2: i32) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { x1_: x1, x2_: x2 })); let this: Ptr = __this.as_pointer(); - (*(*this.upgrade().deref()).x1_.borrow_mut()).prefix_inc(); - (*(*this.upgrade().deref()).x2_.borrow_mut()).prefix_dec(); + field!(this, x1_).with_mut(|__v| __v.prefix_inc()); + field!(this, x2_).with_mut(|__v| __v.prefix_dec()); Rc::try_unwrap(__this).ok().unwrap().into_inner() } } -impl Clone for StructWithCtor { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - x1_: Rc::new(RefCell::new((*self.x1_.borrow()))), - x2_: Rc::new(RefCell::new((*self.x2_.borrow()))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} -impl ByteRepr for StructWithCtor { - fn byte_size() -> usize { - 8 - } - fn to_bytes(&self, buf: &mut [u8]) { - (*self.x1_.borrow()).to_bytes(&mut buf[0..4]); - (*self.x2_.borrow()).to_bytes(&mut buf[4..8]); - } - fn from_bytes(buf: &[u8]) -> Self { - Self { - x1_: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), - x2_: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), - } - } -} pub fn foo_0(x: Ptr) -> Ptr { return (x).clone(); } -#[derive(VaArg, FnPtrArg, Default)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(4)] pub struct Value_ { - pub v: Value, + #[offset(0)] + pub v: i32, } 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]))), - } + pub fn new(mut u: i32) -> Self { + Self { v: u } } } -#[derive(VaArg, FnPtrArg)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg)] +#[byte_size(8)] pub struct Ptr_ { - pub v1: Value, - pub v2: Value, + #[offset(0)] + #[byte_size(4)] + pub v1: Value_, + #[offset(4)] + #[byte_size(4)] + 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() + Self { + v1: Value_::new({ 11 }), + v2: Value_::new({ 22 }), + } } } impl Default for Ptr_ { @@ -119,21 +60,6 @@ impl Default for Ptr_ { { 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()); @@ -147,9 +73,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)); + let mut p: Ptr_ = Ptr_::new(); + assert!((p.v1.v == 11)); + assert!((p.v2.v == 22)); return 0; } pub trait StructWithCtorImpl { @@ -158,10 +84,10 @@ pub trait StructWithCtorImpl { } impl StructWithCtorImpl for Ptr { fn x1(&self) -> Ptr { - return (*(*self).upgrade().deref()).x1_.as_pointer(); + return field_ptr!((*self), x1_); } fn x2(&self) -> Ptr { - return (*(*self).upgrade().deref()).x2_.as_pointer(); + return field_ptr!((*self), x2_); } } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_array.rs b/tests/unit/out/refcount/structured_binding_array.rs index 3917de173..c31977dc3 100644 --- a/tests/unit/out/refcount/structured_binding_array.rs +++ b/tests/unit/out/refcount/structured_binding_array.rs @@ -12,20 +12,19 @@ pub fn main() { } fn main_0() -> i32 { let arr: Value> = Rc::new(RefCell::new(Box::new([1, 2, 3]))); - let __decomp_0: Value> = - Rc::new(RefCell::new(Box::new(std::array::from_fn::<_, 3, _>( - |__i: usize| (*arr.borrow())[(__i) as usize], - )))); - (*__decomp_0.borrow_mut())[(0) as usize] = 10; - assert!(((*__decomp_0.borrow())[(0) as usize] == 10)); - assert!(((*__decomp_0.borrow())[(1) as usize] == 2)); - assert!(((*__decomp_0.borrow())[(2) as usize] == 3)); + let mut __decomp_0: [i32; 3] = Box::new(std::array::from_fn::<_, 3, _>(|__i: usize| { + (*arr.borrow())[(__i) as usize] + })); + __decomp_0[(0) as usize] = 10; + assert!((__decomp_0[(0) as usize] == 10)); + assert!((__decomp_0[(1) as usize] == 2)); + assert!((__decomp_0[(2) as usize] == 3)); assert!(((*arr.borrow())[(0) as usize] == 1)); - let __decomp_1: Ptr = (arr.as_pointer() as Ptr); - (__decomp_1).offset((0) as isize).write(7); + let __decomp_1: Ptr = arr.as_pointer(); + elem!((__decomp_1), 0).write(7); { - let _ptr = (__decomp_1).offset((2) as isize); - _ptr.write(_ptr.read() + ((__decomp_1).offset((1) as isize).read())) + let __rhs = (elem!((__decomp_1), 1).read()); + elem!((__decomp_1), 2).with_mut(|__v| *__v = *__v + __rhs) }; assert!(((*arr.borrow())[(0) as usize] == 7)); assert!(((*arr.borrow())[(2) as usize] == 5)); diff --git a/tests/unit/out/refcount/structured_binding_copy_ctor.rs b/tests/unit/out/refcount/structured_binding_copy_ctor.rs index c71bcef66..cf8c263fc 100644 --- a/tests/unit/out/refcount/structured_binding_copy_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_copy_ctor.rs @@ -9,30 +9,25 @@ use std::rc::{Rc, Weak}; thread_local!( pub static copies_0: Value = Rc::new(RefCell::new(0)); ); -#[derive(VaArg, FnPtrArg, Default)] +#[derive(Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(8)] pub struct Counted { - pub x: Value, - pub y: Value, + #[offset(0)] + pub x: i32, + #[offset(4)] + pub y: i32, } impl Counted { - pub fn new(x: i32, y: i32) -> Self { - let x: Value = Rc::new(RefCell::new(x)); - let y: Value = Rc::new(RefCell::new(y)); - let __this: Value = Rc::new(RefCell::new(Self { - x: Rc::new(RefCell::new((*x.borrow()))), - y: Rc::new(RefCell::new((*y.borrow()))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + pub fn new(mut x: i32, mut y: i32) -> Self { + Self { x: x, y: y } } pub fn copy_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - x: Rc::new(RefCell::new(((*(*other.upgrade().deref()).x.borrow()) * 2))), - y: Rc::new(RefCell::new(((*(*other.upgrade().deref()).y.borrow()) * 2))), - })); - let this: Ptr = __this.as_pointer(); + let __this: Counted = Self { + x: (other.with(|__s| __s.x) * 2), + y: (other.with(|__s| __s.y) * 2), + }; (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } } impl Clone for Counted { @@ -44,21 +39,6 @@ impl Clone for Counted { Counted::copy_from(__src.as_pointer()) } } -impl ByteRepr for Counted { - fn byte_size() -> usize { - 8 - } - fn to_bytes(&self, buf: &mut [u8]) { - (*self.x.borrow()).to_bytes(&mut buf[0..4]); - (*self.y.borrow()).to_bytes(&mut buf[4..8]); - } - fn from_bytes(buf: &[u8]) -> Self { - Self { - x: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), - y: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), - } - } -} pub fn make_counted_1() -> Counted { return Counted::new({ 5 }, { 6 }); } @@ -68,21 +48,21 @@ pub fn main() { } fn main_0() -> i32 { let s: Value = Rc::new(RefCell::new(Counted::new({ 1 }, { 2 }))); - let __decomp_2: Value = Rc::new(RefCell::new(Counted::copy_from({ s.as_pointer() }))); + let mut __decomp_2: Counted = Counted::copy_from({ s.as_pointer() }); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!(((*(*__decomp_2.borrow()).x.borrow()) == 2)); - assert!(((*(*__decomp_2.borrow()).y.borrow()) == 4)); + assert!((__decomp_2.x == 2)); + assert!((__decomp_2.y == 4)); let __decomp_3: Ptr = s.as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!(((*(*__decomp_3.upgrade().deref()).x.borrow()) == 1)); - assert!(((*(*__decomp_3.upgrade().deref()).y.borrow()) == 2)); + assert!((__decomp_3.with(|__s| __s.x) == 1)); + assert!((__decomp_3.with(|__s| __s.y) == 2)); let __decomp_4: Ptr = s.as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!(((*(*__decomp_4.upgrade().deref()).x.borrow()) == 1)); - let __decomp_5: Value = Rc::new(RefCell::new(({ make_counted_1() }))); + assert!((__decomp_4.with(|__s| __s.x) == 1)); + let mut __decomp_5: Counted = ({ make_counted_1() }); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!(((*(*__decomp_5.borrow()).x.borrow()) == 5)); - assert!(((*(*__decomp_5.borrow()).y.borrow()) == 6)); + assert!((__decomp_5.x == 5)); + assert!((__decomp_5.y == 6)); return 0; } pub fn __cpp2rust_init_globals() { diff --git a/tests/unit/out/refcount/structured_binding_element_ctor.rs b/tests/unit/out/refcount/structured_binding_element_ctor.rs index 1d4d41ae8..56378903b 100644 --- a/tests/unit/out/refcount/structured_binding_element_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_element_ctor.rs @@ -12,39 +12,30 @@ thread_local!( thread_local!( pub static moves_1: Value = Rc::new(RefCell::new(0)); ); -#[derive(VaArg, FnPtrArg, Default)] +#[derive(Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)] +#[byte_size(4)] pub struct Elem { - pub v: Value, + #[offset(0)] + pub v: i32, } impl Elem { - pub fn new(v: i32) -> Self { - let v: Value = Rc::new(RefCell::new(v)); - let __this: Value = Rc::new(RefCell::new(Self { - v: Rc::new(RefCell::new((*v.borrow()))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + pub fn new(mut v: i32) -> Self { + Self { v: v } } pub fn copy_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - v: Rc::new(RefCell::new( - ((*(*other.upgrade().deref()).v.borrow()) + 100), - )), - })); - let this: Ptr = __this.as_pointer(); + let __this: Elem = Self { + v: (other.with(|__s| __s.v) + 100), + }; (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } pub fn move_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - v: Rc::new(RefCell::new( - ((*(*other.upgrade().deref()).v.borrow()) + 1000), - )), - })); - let this: Ptr = __this.as_pointer(); - (*(*other.upgrade().deref()).v.borrow_mut()) = -1_i32; + let __this: Elem = Self { + v: (other.with(|__s| __s.v) + 1000), + }; + field!(other, v).write(-1_i32); (*moves_1.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } } impl Clone for Elem { @@ -53,53 +44,20 @@ impl Clone for Elem { Elem::copy_from(__src.as_pointer()) } } -impl ByteRepr for Elem { - 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(VaArg, FnPtrArg, Default)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(8)] pub struct Two { - pub a: Value, - pub b: Value, -} -impl Clone for Two { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - a: Rc::new(RefCell::new(Elem::copy_from({ self.a.as_pointer() }))), - b: Rc::new(RefCell::new(Elem::copy_from({ self.b.as_pointer() }))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} -impl ByteRepr for Two { - fn byte_size() -> usize { - 8 - } - fn to_bytes(&self, buf: &mut [u8]) { - (*self.a.borrow()).to_bytes(&mut buf[0..4]); - (*self.b.borrow()).to_bytes(&mut buf[4..8]); - } - fn from_bytes(buf: &[u8]) -> Self { - Self { - a: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), - b: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), - } - } + #[offset(0)] + #[byte_size(4)] + pub a: Elem, + #[offset(4)] + #[byte_size(4)] + pub b: Elem, } pub fn make_two_2() -> Two { return Two { - a: Rc::new(RefCell::new(Elem::new({ 1 }))), - b: Rc::new(RefCell::new(Elem::new({ 2 }))), + a: Elem::new({ 1 }), + b: Elem::new({ 2 }), }; } pub fn main() { @@ -108,32 +66,32 @@ pub fn main() { } fn main_0() -> i32 { let t: Value = Rc::new(RefCell::new(Two { - a: Rc::new(RefCell::new(Elem::new({ 1 }))), - b: Rc::new(RefCell::new(Elem::new({ 2 }))), + a: Elem::new({ 1 }), + b: Elem::new({ 2 }), })); - let base_copies: Value = Rc::new(RefCell::new(copies_0.with(|rc| *rc.borrow()))); - let base_moves: Value = Rc::new(RefCell::new(moves_1.with(|rc| *rc.borrow()))); - let __decomp_3: Value = Rc::new(RefCell::new((*t.borrow()).clone())); - assert!((copies_0.with(|rc| *rc.borrow()) == ((*base_copies.borrow()) + 2))); - assert!((moves_1.with(|rc| *rc.borrow()) == (*base_moves.borrow()))); - assert!(((*(*(*__decomp_3.borrow()).a.borrow()).v.borrow()) == 101)); - assert!(((*(*(*__decomp_3.borrow()).b.borrow()).v.borrow()) == 102)); + let mut base_copies: i32 = copies_0.with(|rc| *rc.borrow()); + let mut base_moves: i32 = moves_1.with(|rc| *rc.borrow()); + let mut __decomp_3: Two = (*t.borrow()).clone(); + assert!((copies_0.with(|rc| *rc.borrow()) == (base_copies + 2))); + assert!((moves_1.with(|rc| *rc.borrow()) == base_moves)); + assert!(({ __decomp_3.a.v } == 101)); + assert!(({ __decomp_3.b.v } == 102)); let __decomp_4: Ptr = t.as_pointer(); - assert!((copies_0.with(|rc| *rc.borrow()) == ((*base_copies.borrow()) + 2))); - assert!(((*(*(*__decomp_4.upgrade().deref()).a.borrow()).v.borrow()) == 1)); - (*(*(*__decomp_4.upgrade().deref()).a.borrow()).v.borrow_mut()) = 50; - assert!(((*(*(*t.borrow()).a.borrow()).v.borrow()) == 50)); - let __decomp_5: Value = Rc::new(RefCell::new((*t.borrow()).clone())); - assert!((moves_1.with(|rc| *rc.borrow()) == ((*base_moves.borrow()) + 2))); - assert!(((*(*(*__decomp_5.borrow()).a.borrow()).v.borrow()) == 1050)); - assert!(((*(*(*__decomp_5.borrow()).b.borrow()).v.borrow()) == 1002)); - assert!(((*(*(*t.borrow()).a.borrow()).v.borrow()) == -1_i32)); - let before_copies: Value = Rc::new(RefCell::new(copies_0.with(|rc| *rc.borrow()))); - let before_moves: Value = Rc::new(RefCell::new(moves_1.with(|rc| *rc.borrow()))); - let __decomp_6: Value = Rc::new(RefCell::new(({ make_two_2() }))); - assert!((copies_0.with(|rc| *rc.borrow()) == (*before_copies.borrow()))); - assert!((moves_1.with(|rc| *rc.borrow()) == (*before_moves.borrow()))); - assert!(((*(*(*__decomp_6.borrow()).a.borrow()).v.borrow()) == 1)); + assert!((copies_0.with(|rc| *rc.borrow()) == (base_copies + 2))); + assert!(({ (*__decomp_4.upgrade().deref()).a.v } == 1)); + field!(field!(__decomp_4, a), v).write(50); + assert!(({ (*t.borrow()).a.v } == 50)); + let mut __decomp_5: Two = (*t.borrow()).clone(); + assert!((moves_1.with(|rc| *rc.borrow()) == (base_moves + 2))); + assert!(({ __decomp_5.a.v } == 1050)); + assert!(({ __decomp_5.b.v } == 1002)); + assert!(({ (*t.borrow()).a.v } == -1_i32)); + let mut before_copies: i32 = copies_0.with(|rc| *rc.borrow()); + let mut before_moves: i32 = moves_1.with(|rc| *rc.borrow()); + let mut __decomp_6: Two = ({ make_two_2() }); + assert!((copies_0.with(|rc| *rc.borrow()) == before_copies)); + assert!((moves_1.with(|rc| *rc.borrow()) == before_moves)); + assert!(({ __decomp_6.a.v } == 1)); let p: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new( Elem::new({ 7 }).try_into().expect("failed conversion"), @@ -142,18 +100,14 @@ fn main_0() -> i32 { Elem::new({ 8 }).try_into().expect("failed conversion"), )), ))); - (*before_copies.borrow_mut()) = copies_0.with(|rc| *rc.borrow()); + before_copies = copies_0.with(|rc| *rc.borrow()); let __decomp_7: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), ))); - assert!((copies_0.with(|rc| *rc.borrow()) == ((*before_copies.borrow()) + 2))); - assert!( - ((*(*x.upgrade().deref()).v.borrow()) == ((*(*(*p.borrow()).0.borrow()).v.borrow()) + 100)) - ); - assert!( - ((*(*y.upgrade().deref()).v.borrow()) == ((*(*(*p.borrow()).1.borrow()).v.borrow()) + 100)) - ); + assert!((copies_0.with(|rc| *rc.borrow()) == (before_copies + 2))); + assert!(({ (*x.upgrade().deref()).v } == ({ (*(*p.borrow()).0.borrow()).v } + 100))); + assert!(({ (*y.upgrade().deref()).v } == ({ (*(*p.borrow()).1.borrow()).v } + 100))); return 0; } pub fn __cpp2rust_init_globals() { diff --git a/tests/unit/out/refcount/structured_binding_move_ctor.rs b/tests/unit/out/refcount/structured_binding_move_ctor.rs index 9e7e07869..7e414bb44 100644 --- a/tests/unit/out/refcount/structured_binding_move_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_move_ctor.rs @@ -12,41 +12,35 @@ thread_local!( thread_local!( pub static moves_1: Value = Rc::new(RefCell::new(0)); ); -#[derive(VaArg, FnPtrArg, Default)] +#[derive(Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)] +#[byte_size(8)] pub struct Movable { - pub x: Value, - pub y: Value, + #[offset(0)] + pub x: i32, + #[offset(4)] + pub y: i32, } impl Movable { - pub fn new(x: i32, y: i32) -> Self { - let x: Value = Rc::new(RefCell::new(x)); - let y: Value = Rc::new(RefCell::new(y)); - let __this: Value = Rc::new(RefCell::new(Self { - x: Rc::new(RefCell::new((*x.borrow()))), - y: Rc::new(RefCell::new((*y.borrow()))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + pub fn new(mut x: i32, mut y: i32) -> Self { + Self { x: x, y: y } } pub fn copy_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - x: Rc::new(RefCell::new((*(*other.upgrade().deref()).x.borrow()))), - y: Rc::new(RefCell::new((*(*other.upgrade().deref()).y.borrow()))), - })); - let this: Ptr = __this.as_pointer(); + let __this: Movable = Self { + x: other.with(|__s| __s.x), + y: other.with(|__s| __s.y), + }; (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } pub fn move_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - x: Rc::new(RefCell::new((*(*other.upgrade().deref()).x.borrow()))), - y: Rc::new(RefCell::new((*(*other.upgrade().deref()).y.borrow()))), - })); - let this: Ptr = __this.as_pointer(); - (*(*other.upgrade().deref()).x.borrow_mut()) = 0; - (*(*other.upgrade().deref()).y.borrow_mut()) = 0; + let __this: Movable = Self { + x: other.with(|__s| __s.x), + y: other.with(|__s| __s.y), + }; + field!(other, x).write(0); + field!(other, y).write(0); (*moves_1.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } } impl Clone for Movable { @@ -58,86 +52,40 @@ impl Clone for Movable { Movable::copy_from(__src.as_pointer()) } } -impl ByteRepr for Movable { - fn byte_size() -> usize { - 8 - } - fn to_bytes(&self, buf: &mut [u8]) { - (*self.x.borrow()).to_bytes(&mut buf[0..4]); - (*self.y.borrow()).to_bytes(&mut buf[4..8]); - } - fn from_bytes(buf: &[u8]) -> Self { - Self { - x: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), - y: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), - } - } -} -#[derive(VaArg, FnPtrArg, Default)] +#[derive(DeepClone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(48)] pub struct Holder { + #[offset(0)] + #[byte_size(24)] pub xs: Value>, + #[offset(24)] + #[byte_size(24)] pub ys: Value>, } -impl Clone for Holder { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - xs: Rc::new(RefCell::new((*self.xs.borrow()).clone())), - ys: Rc::new(RefCell::new((*self.ys.borrow()).clone())), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} -impl ByteRepr for Holder { - fn byte_size() -> usize { - 48 - } - fn to_bytes(&self, buf: &mut [u8]) { - (*self.xs.borrow()).to_bytes(&mut buf[0..24]); - (*self.ys.borrow()).to_bytes(&mut buf[24..48]); - } - fn from_bytes(buf: &[u8]) -> Self { - Self { - xs: Rc::new(RefCell::new(>::from_bytes(&buf[0..24]))), - ys: Rc::new(RefCell::new(>::from_bytes(&buf[24..48]))), - } - } -} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); } fn main_0() -> i32 { let m: Value = Rc::new(RefCell::new(Movable::new({ 3 }, { 4 }))); - let __decomp_2: Value = Rc::new(RefCell::new(Movable::move_from({ m.as_pointer() }))); + let mut __decomp_2: Movable = Movable::move_from({ m.as_pointer() }); assert!((moves_1.with(|rc| *rc.borrow()) == 1)); assert!((copies_0.with(|rc| *rc.borrow()) == 0)); - assert!(((*(*__decomp_2.borrow()).x.borrow()) == 3)); - assert!(((*(*__decomp_2.borrow()).y.borrow()) == 4)); - assert!(((*(*m.borrow()).x.borrow()) == 0)); - assert!(((*(*m.borrow()).y.borrow()) == 0)); + assert!((__decomp_2.x == 3)); + assert!((__decomp_2.y == 4)); + assert!(({ (*m.borrow()).x } == 0)); + assert!(({ (*m.borrow()).y } == 0)); let h: Value = Rc::new(RefCell::new(Holder { xs: Rc::new(RefCell::new(vec![1, 2, 3])), ys: Rc::new(RefCell::new(vec![4, 5])), })); - let __decomp_3: Value = - Rc::new(RefCell::new(({ HolderImpl::extract(&h.as_pointer()) }))); - assert!(((*(*__decomp_3.borrow()).xs.borrow()).len() == 3_usize)); - assert!(((*(*__decomp_3.borrow()).ys.borrow()).len() == 2_usize)); - assert!( - ((((*__decomp_3.borrow()).xs.as_pointer() as Ptr) - .offset(2_usize) - .read()) - == 3) - ); - assert!( - ((((*__decomp_3.borrow()).ys.as_pointer() as Ptr) - .offset(0_usize) - .read()) - == 4) - ); - assert!((*(*h.borrow()).xs.borrow()).is_empty()); - assert!((*(*h.borrow()).ys.borrow()).is_empty()); + let mut __decomp_3: Holder = ({ HolderImpl::extract(&h.as_pointer()) }); + assert!(((*__decomp_3.xs.borrow()).len() == 3_usize)); + assert!(((*__decomp_3.ys.borrow()).len() == 2_usize)); + assert!(((elem!((__decomp_3.xs.as_pointer() as Ptr), 2_usize).read()) == 3)); + assert!(((elem!((__decomp_3.ys.as_pointer() as Ptr), 0_usize).read()) == 4)); + assert!((*{ (*h.borrow()).xs.clone() }.borrow()).is_empty()); + assert!((*{ (*h.borrow()).ys.clone() }.borrow()).is_empty()); return 0; } pub trait HolderImpl { @@ -147,10 +95,10 @@ impl HolderImpl for Ptr { fn extract(&self) -> Holder { return Holder { xs: Rc::new(RefCell::new(std::mem::take( - &mut (*(*(*self).upgrade().deref()).xs.borrow_mut()), + &mut (*(*self).with(|__s| __s.xs.clone()).borrow_mut()), ))), ys: Rc::new(RefCell::new(std::mem::take( - &mut (*(*(*self).upgrade().deref()).ys.borrow_mut()), + &mut (*(*self).with(|__s| __s.ys.clone()).borrow_mut()), ))), }; } diff --git a/tests/unit/out/refcount/structured_binding_pair.rs b/tests/unit/out/refcount/structured_binding_pair.rs index b9c3e0278..42fce15c2 100644 --- a/tests/unit/out/refcount/structured_binding_pair.rs +++ b/tests/unit/out/refcount/structured_binding_pair.rs @@ -6,15 +6,10 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -pub fn make_std_pair_0(x: i32) -> (Value, Value) { - let x: Value = Rc::new(RefCell::new(x)); +pub fn make_std_pair_0(mut x: i32) -> (Value, Value) { return ( - Rc::new(RefCell::new( - (*x.borrow()).try_into().expect("failed conversion"), - )), - Rc::new(RefCell::new( - ((*x.borrow()) > 0).try_into().expect("failed conversion"), - )), + Rc::new(RefCell::new(x.try_into().expect("failed conversion"))), + Rc::new(RefCell::new((x > 0).try_into().expect("failed conversion"))), ); } pub fn main() { @@ -41,8 +36,7 @@ fn main_0() -> i32 { let __decomp_3: Ptr<(Value, Value)> = p.as_pointer(); x.write(3); { - let _ptr = y.clone(); - _ptr.write(_ptr.read() + 4) + y.with_mut(|__v| *__v = *__v + 4) }; assert!(((*(*p.borrow()).0.borrow()) == 3)); assert!(((*(*p.borrow()).1.borrow()) == 6)); diff --git a/tests/unit/out/refcount/structured_binding_range_for.rs b/tests/unit/out/refcount/structured_binding_range_for.rs index 90bcbe0dc..0abc1cdb8 100644 --- a/tests/unit/out/refcount/structured_binding_range_for.rs +++ b/tests/unit/out/refcount/structured_binding_range_for.rs @@ -6,35 +6,13 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -#[derive(VaArg, FnPtrArg, Default)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(8)] pub struct Pair { - pub first: Value, - pub second: Value, -} -impl Clone for Pair { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - first: Rc::new(RefCell::new((*self.first.borrow()))), - second: Rc::new(RefCell::new((*self.second.borrow()))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} -impl ByteRepr for Pair { - fn byte_size() -> usize { - 8 - } - fn to_bytes(&self, buf: &mut [u8]) { - (*self.first.borrow()).to_bytes(&mut buf[0..4]); - (*self.second.borrow()).to_bytes(&mut buf[4..8]); - } - fn from_bytes(buf: &[u8]) -> Self { - Self { - first: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), - second: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), - } - } + #[offset(0)] + pub first: i32, + #[offset(4)] + pub second: i32, } pub fn main() { __cpp2rust_init_globals(); @@ -43,37 +21,38 @@ pub fn main() { fn main_0() -> i32 { let arr: Value> = Rc::new(RefCell::new(Box::new([ Pair { - first: Rc::new(RefCell::new(1)), - second: Rc::new(RefCell::new(2)), + first: 1, + second: 2, }, Pair { - first: Rc::new(RefCell::new(3)), - second: Rc::new(RefCell::new(4)), + first: 3, + second: 4, }, Pair { - first: Rc::new(RefCell::new(5)), - second: Rc::new(RefCell::new(6)), + first: 5, + second: 6, }, ]))); 'loop_: for mut __decomp_0 in arr.as_pointer() as Ptr { - (*(*__decomp_0.upgrade().deref()).first.borrow_mut()) += - (*(*__decomp_0.upgrade().deref()).second.borrow()); + { + let __rhs = __decomp_0.with(|__s| __s.second); + field!(__decomp_0, first).with_mut(|__v| *__v = *__v + __rhs) + }; } - assert!(((*(*arr.borrow())[(0) as usize].first.borrow()) == 3)); - assert!(((*(*arr.borrow())[(2) as usize].first.borrow()) == 11)); + assert!(({ (*arr.borrow())[(0) as usize].first } == 3)); + assert!(({ (*arr.borrow())[(2) as usize].first } == 11)); 'loop_: for mut __decomp_1 in arr.as_pointer() as Ptr { - let __decomp_1: Value = Rc::new(RefCell::new(__decomp_1.upgrade().deref().clone())); - (*(*__decomp_1.borrow()).first.borrow_mut()) = 0; - (*(*__decomp_1.borrow()).second.borrow_mut()) = 0; + let mut __decomp_1: Pair = __decomp_1.upgrade().deref().clone(); + __decomp_1.first = 0; + __decomp_1.second = 0; } - assert!(((*(*arr.borrow())[(1) as usize].first.borrow()) == 7)); - assert!(((*(*arr.borrow())[(1) as usize].second.borrow()) == 4)); - let sum: Value = Rc::new(RefCell::new(0)); + assert!(({ (*arr.borrow())[(1) as usize].first } == 7)); + assert!(({ (*arr.borrow())[(1) as usize].second } == 4)); + let mut sum: i32 = 0; 'loop_: for mut __decomp_2 in arr.as_pointer() as Ptr { - (*sum.borrow_mut()) += ((*(*__decomp_2.upgrade().deref()).first.borrow()) - * (*(*__decomp_2.upgrade().deref()).second.borrow())); + sum += (__decomp_2.with(|__s| __s.first) * __decomp_2.with(|__s| __s.second)); } - assert!(((*sum.borrow()) == (((3 * 2) + (7 * 4)) + (11 * 6)))); + assert!((sum == (((3 * 2) + (7 * 4)) + (11 * 6)))); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_ref.rs b/tests/unit/out/refcount/structured_binding_ref.rs index 48c3003b6..ba4e6f54e 100644 --- a/tests/unit/out/refcount/structured_binding_ref.rs +++ b/tests/unit/out/refcount/structured_binding_ref.rs @@ -6,49 +6,20 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -#[derive(VaArg, FnPtrArg, Default)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(12)] pub struct Triple { - pub a: Value, - pub b: Value, - pub c: Value, -} -impl Clone for Triple { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - a: Rc::new(RefCell::new((*self.a.borrow()))), - b: Rc::new(RefCell::new((*self.b.borrow()))), - c: Rc::new(RefCell::new((*self.c.borrow()))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} -impl ByteRepr for Triple { - fn byte_size() -> usize { - 12 - } - fn to_bytes(&self, buf: &mut [u8]) { - (*self.a.borrow()).to_bytes(&mut buf[0..4]); - (*self.b.borrow()).to_bytes(&mut buf[4..5]); - (*self.c.borrow()).to_bytes(&mut buf[8..12]); - } - fn from_bytes(buf: &[u8]) -> Self { - Self { - a: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), - b: Rc::new(RefCell::new(::from_bytes(&buf[4..5]))), - c: Rc::new(RefCell::new(::from_bytes(&buf[8..12]))), - } - } + #[offset(0)] + pub a: i32, + #[offset(4)] + pub b: bool, + #[offset(8)] + pub c: i32, } pub fn sum_0(t: Ptr) -> i32 { let __decomp_1: Ptr = (t).clone(); - return (((*(*__decomp_1.upgrade().deref()).a.borrow()) - + (if (*(*__decomp_1.upgrade().deref()).b.borrow()) { - 1 - } else { - 0 - })) - + (*(*__decomp_1.upgrade().deref()).c.borrow())); + return ((__decomp_1.with(|__s| __s.a) + (if __decomp_1.with(|__s| __s.b) { 1 } else { 0 })) + + __decomp_1.with(|__s| __s.c)); } pub fn main() { __cpp2rust_init_globals(); @@ -56,24 +27,26 @@ pub fn main() { } fn main_0() -> i32 { let t: Value = Rc::new(RefCell::new(Triple { - a: Rc::new(RefCell::new(10)), - b: Rc::new(RefCell::new(false)), - c: Rc::new(RefCell::new(20)), + a: 10, + b: false, + c: 20, })); let __decomp_2: Ptr = t.as_pointer(); - (*(*__decomp_2.upgrade().deref()).a.borrow_mut()) = 11; - (*(*__decomp_2.upgrade().deref()).b.borrow_mut()) = true; - (*(*__decomp_2.upgrade().deref()).c.borrow_mut()) += 1; - assert!(((*(*t.borrow()).a.borrow()) == 11)); - assert!((*(*t.borrow()).b.borrow())); - assert!(((*(*t.borrow()).c.borrow()) == 21)); - (*(*t.borrow()).a.borrow_mut()) = 12; - assert!(((*(*__decomp_2.upgrade().deref()).a.borrow()) == 12)); + field!(__decomp_2, a).write(11); + field!(__decomp_2, b).write(true); + { + field!(__decomp_2, c).with_mut(|__v| *__v = *__v + 1) + }; + assert!(({ (*t.borrow()).a } == 11)); + assert!({ (*t.borrow()).b }); + assert!(({ (*t.borrow()).c } == 21)); + (*t.borrow_mut()).a = 12; + assert!((__decomp_2.with(|__s| __s.a) == 12)); let __decomp_3: Ptr = t.as_pointer(); - (*(*t.borrow()).c.borrow_mut()) = 30; - assert!(((*(*__decomp_3.upgrade().deref()).a.borrow()) == 12)); - assert!((*(*__decomp_3.upgrade().deref()).b.borrow())); - assert!(((*(*__decomp_3.upgrade().deref()).c.borrow()) == 30)); + (*t.borrow_mut()).c = 30; + assert!((__decomp_3.with(|__s| __s.a) == 12)); + assert!(__decomp_3.with(|__s| __s.b)); + assert!((__decomp_3.with(|__s| __s.c) == 30)); assert!((({ sum_0(t.as_pointer(),) }) == 43)); return 0; } diff --git a/tests/unit/out/refcount/structured_binding_trivial.rs b/tests/unit/out/refcount/structured_binding_trivial.rs index 03e0572ec..29c206941 100644 --- a/tests/unit/out/refcount/structured_binding_trivial.rs +++ b/tests/unit/out/refcount/structured_binding_trivial.rs @@ -6,58 +6,36 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -#[derive(VaArg, FnPtrArg, Default)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(8)] pub struct Pair { - pub first: Value, - pub second: Value, -} -impl Clone for Pair { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - first: Rc::new(RefCell::new((*self.first.borrow()))), - second: Rc::new(RefCell::new((*self.second.borrow()))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} -impl ByteRepr for Pair { - fn byte_size() -> usize { - 8 - } - fn to_bytes(&self, buf: &mut [u8]) { - (*self.first.borrow()).to_bytes(&mut buf[0..4]); - (*self.second.borrow()).to_bytes(&mut buf[4..8]); - } - fn from_bytes(buf: &[u8]) -> Self { - Self { - first: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), - second: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), - } - } + #[offset(0)] + pub first: i32, + #[offset(4)] + pub second: i32, } pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); } fn main_0() -> i32 { - let __decomp_0: Value = Rc::new(RefCell::new(Pair { - first: Rc::new(RefCell::new(1)), - second: Rc::new(RefCell::new(2)), - })); - assert!(((*(*__decomp_0.borrow()).first.borrow()) == 1)); - assert!(((*(*__decomp_0.borrow()).second.borrow()) == 2)); - let p: Value = Rc::new(RefCell::new(Pair { - first: Rc::new(RefCell::new(10)), - second: Rc::new(RefCell::new(20)), - })); - let __decomp_1: Value = Rc::new(RefCell::new((*p.borrow()).clone())); - (*(*__decomp_1.borrow()).first.borrow_mut()) = 11; - (*(*__decomp_1.borrow()).second.borrow_mut()) += 1; - assert!(((*(*__decomp_1.borrow()).first.borrow()) == 11)); - assert!(((*(*__decomp_1.borrow()).second.borrow()) == 21)); - assert!(((*(*p.borrow()).first.borrow()) == 10)); - assert!(((*(*p.borrow()).second.borrow()) == 20)); + let mut __decomp_0: Pair = Pair { + first: 1, + second: 2, + }; + assert!((__decomp_0.first == 1)); + assert!((__decomp_0.second == 2)); + let mut p: Pair = Pair { + first: 10, + second: 20, + }; + let mut __decomp_1: Pair = (p).clone(); + __decomp_1.first = 11; + __decomp_1.second += 1; + assert!((__decomp_1.first == 11)); + assert!((__decomp_1.second == 21)); + assert!((p.first == 10)); + assert!((p.second == 20)); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/struct_ctor.rs b/tests/unit/out/unsafe/struct_ctor.rs index 30a92872a..8e8b0a792 100644 --- a/tests/unit/out/unsafe/struct_ctor.rs +++ b/tests/unit/out/unsafe/struct_ctor.rs @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] -#[derive(Copy, Clone, VaArg, Default)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] pub struct StructWithCtor { x1_: i32, x2_: i32, @@ -30,7 +30,7 @@ pub unsafe fn foo_0(x: *mut i32) -> *mut i32 { return x; } #[repr(C)] -#[derive(Copy, Clone, VaArg, Default)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] pub struct Value_ { pub v: i32, } @@ -41,7 +41,7 @@ impl Value_ { } } #[repr(C)] -#[derive(Copy, Clone, VaArg)] +#[derive(Copy, Clone, VaArg, FnPtrArg)] pub struct Ptr_ { pub v1: Value_, pub v2: Value_, diff --git a/tests/unit/out/unsafe/structured_binding_copy_ctor.rs b/tests/unit/out/unsafe/structured_binding_copy_ctor.rs index db490f085..003a2be14 100644 --- a/tests/unit/out/unsafe/structured_binding_copy_ctor.rs +++ b/tests/unit/out/unsafe/structured_binding_copy_ctor.rs @@ -8,7 +8,7 @@ use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub static mut copies_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); #[repr(C)] -#[derive(VaArg, Default)] +#[derive(VaArg, FnPtrArg, Default)] pub struct Counted { pub x: i32, pub y: i32, diff --git a/tests/unit/out/unsafe/structured_binding_element_ctor.rs b/tests/unit/out/unsafe/structured_binding_element_ctor.rs index e7ee9217d..b208fc58b 100644 --- a/tests/unit/out/unsafe/structured_binding_element_ctor.rs +++ b/tests/unit/out/unsafe/structured_binding_element_ctor.rs @@ -9,7 +9,7 @@ use std::rc::Rc; pub static mut copies_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); pub static mut moves_1: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); #[repr(C)] -#[derive(VaArg, Default)] +#[derive(VaArg, FnPtrArg, MoveCtorUnsafe, Default)] pub struct Elem { pub v: i32, } @@ -40,7 +40,7 @@ impl Clone for Elem { } } #[repr(C)] -#[derive(Clone, VaArg, Default)] +#[derive(Clone, VaArg, FnPtrArg, Default)] pub struct Two { pub a: Elem, pub b: Elem, diff --git a/tests/unit/out/unsafe/structured_binding_move_ctor.rs b/tests/unit/out/unsafe/structured_binding_move_ctor.rs index cf062bccb..21baab73d 100644 --- a/tests/unit/out/unsafe/structured_binding_move_ctor.rs +++ b/tests/unit/out/unsafe/structured_binding_move_ctor.rs @@ -9,7 +9,7 @@ use std::rc::Rc; pub static mut copies_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); pub static mut moves_1: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); #[repr(C)] -#[derive(VaArg, Default)] +#[derive(VaArg, FnPtrArg, MoveCtorUnsafe, Default)] pub struct Movable { pub x: i32, pub y: i32, @@ -44,7 +44,7 @@ impl Clone for Movable { } } #[repr(C)] -#[derive(Clone, VaArg, Default)] +#[derive(Clone, VaArg, FnPtrArg, Default)] pub struct Holder { pub xs: Vec, pub ys: Vec, diff --git a/tests/unit/out/unsafe/structured_binding_range_for.rs b/tests/unit/out/unsafe/structured_binding_range_for.rs index b6171ace0..b9de2db73 100644 --- a/tests/unit/out/unsafe/structured_binding_range_for.rs +++ b/tests/unit/out/unsafe/structured_binding_range_for.rs @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] -#[derive(Copy, Clone, VaArg, Default)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] pub struct Pair { pub first: i32, pub second: i32, diff --git a/tests/unit/out/unsafe/structured_binding_ref.rs b/tests/unit/out/unsafe/structured_binding_ref.rs index f6b62d73c..d4a1d567a 100644 --- a/tests/unit/out/unsafe/structured_binding_ref.rs +++ b/tests/unit/out/unsafe/structured_binding_ref.rs @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] -#[derive(Copy, Clone, VaArg, Default)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] pub struct Triple { pub a: i32, pub b: bool, diff --git a/tests/unit/out/unsafe/structured_binding_trivial.rs b/tests/unit/out/unsafe/structured_binding_trivial.rs index 70268c1b2..83de1cec1 100644 --- a/tests/unit/out/unsafe/structured_binding_trivial.rs +++ b/tests/unit/out/unsafe/structured_binding_trivial.rs @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] -#[derive(Copy, Clone, VaArg, Default)] +#[derive(Copy, Clone, VaArg, FnPtrArg, Default)] pub struct Pair { pub first: i32, pub second: i32, From d80e7c5fe3a519083568b65ce90bbccd1a3174ac Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Tue, 29 Sep 2026 20:40:52 +0100 Subject: [PATCH 12/21] Convert implicit values of decomposition --- cpp2rust/converter/converter.cpp | 9 + .../structured_binding_element_ctor.rs | 154 ++++++++++++------ .../out/refcount/structured_binding_pair.rs | 24 ++- .../unsafe/structured_binding_element_ctor.rs | 6 +- .../out/unsafe/structured_binding_pair.rs | 10 +- 5 files changed, 140 insertions(+), 63 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index e57fd50be..6232f7d3b 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -669,6 +669,15 @@ bool Converter::VisitVarDecl(clang::VarDecl *decl) { } EmitScopedDestructor(decl); + if (auto *decomp = clang::dyn_cast(decl)) { + for (auto *binding : decomp->bindings()) { + if (auto *holding = binding->getHoldingVar()) { + StrCat(token::kSemiColon); + VisitVarDecl(holding); + } + } + } + return false; } diff --git a/tests/unit/out/refcount/structured_binding_element_ctor.rs b/tests/unit/out/refcount/structured_binding_element_ctor.rs index 56378903b..6f0054430 100644 --- a/tests/unit/out/refcount/structured_binding_element_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_element_ctor.rs @@ -12,30 +12,39 @@ thread_local!( thread_local!( pub static moves_1: Value = Rc::new(RefCell::new(0)); ); -#[derive(Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)] -#[byte_size(4)] +#[derive(VaArg, FnPtrArg, Default)] pub struct Elem { - #[offset(0)] - pub v: i32, + pub v: Value, } impl Elem { - pub fn new(mut v: i32) -> Self { - Self { v: v } + pub fn new(v: i32) -> Self { + let v: Value = Rc::new(RefCell::new(v)); + let __this: Value = Rc::new(RefCell::new(Self { + v: Rc::new(RefCell::new((*v.borrow()))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() } pub fn copy_from(other: Ptr) -> Self { - let __this: Elem = Self { - v: (other.with(|__s| __s.v) + 100), - }; + let __this: Value = Rc::new(RefCell::new(Self { + v: Rc::new(RefCell::new( + ((*(*other.upgrade().deref()).v.borrow()) + 100), + )), + })); + let this: Ptr = __this.as_pointer(); (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); - __this + Rc::try_unwrap(__this).ok().unwrap().into_inner() } pub fn move_from(other: Ptr) -> Self { - let __this: Elem = Self { - v: (other.with(|__s| __s.v) + 1000), - }; - field!(other, v).write(-1_i32); + let __this: Value = Rc::new(RefCell::new(Self { + v: Rc::new(RefCell::new( + ((*(*other.upgrade().deref()).v.borrow()) + 1000), + )), + })); + let this: Ptr = __this.as_pointer(); + (*(*other.upgrade().deref()).v.borrow_mut()) = -1_i32; (*moves_1.with(Value::clone).borrow_mut()).prefix_inc(); - __this + Rc::try_unwrap(__this).ok().unwrap().into_inner() } } impl Clone for Elem { @@ -44,20 +53,53 @@ impl Clone for Elem { Elem::copy_from(__src.as_pointer()) } } -#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] -#[byte_size(8)] +impl ByteRepr for Elem { + 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(VaArg, FnPtrArg, Default)] pub struct Two { - #[offset(0)] - #[byte_size(4)] - pub a: Elem, - #[offset(4)] - #[byte_size(4)] - pub b: Elem, + pub a: Value, + pub b: Value, +} +impl Clone for Two { + fn clone(&self) -> Self { + let __this: Value = Rc::new(RefCell::new(Self { + a: Rc::new(RefCell::new(Elem::copy_from({ self.a.as_pointer() }))), + b: Rc::new(RefCell::new(Elem::copy_from({ self.b.as_pointer() }))), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() + } +} +impl ByteRepr for Two { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.a.borrow()).to_bytes(&mut buf[0..4]); + (*self.b.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + a: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + b: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } } pub fn make_two_2() -> Two { return Two { - a: Elem::new({ 1 }), - b: Elem::new({ 2 }), + a: Rc::new(RefCell::new(Elem::new({ 1 }))), + b: Rc::new(RefCell::new(Elem::new({ 2 }))), }; } pub fn main() { @@ -66,32 +108,32 @@ pub fn main() { } fn main_0() -> i32 { let t: Value = Rc::new(RefCell::new(Two { - a: Elem::new({ 1 }), - b: Elem::new({ 2 }), + a: Rc::new(RefCell::new(Elem::new({ 1 }))), + b: Rc::new(RefCell::new(Elem::new({ 2 }))), })); - let mut base_copies: i32 = copies_0.with(|rc| *rc.borrow()); - let mut base_moves: i32 = moves_1.with(|rc| *rc.borrow()); - let mut __decomp_3: Two = (*t.borrow()).clone(); - assert!((copies_0.with(|rc| *rc.borrow()) == (base_copies + 2))); - assert!((moves_1.with(|rc| *rc.borrow()) == base_moves)); - assert!(({ __decomp_3.a.v } == 101)); - assert!(({ __decomp_3.b.v } == 102)); + let base_copies: Value = Rc::new(RefCell::new(copies_0.with(|rc| *rc.borrow()))); + let base_moves: Value = Rc::new(RefCell::new(moves_1.with(|rc| *rc.borrow()))); + let __decomp_3: Value = Rc::new(RefCell::new((*t.borrow()).clone())); + assert!((copies_0.with(|rc| *rc.borrow()) == ((*base_copies.borrow()) + 2))); + assert!((moves_1.with(|rc| *rc.borrow()) == (*base_moves.borrow()))); + assert!(((*(*(*__decomp_3.borrow()).a.borrow()).v.borrow()) == 101)); + assert!(((*(*(*__decomp_3.borrow()).b.borrow()).v.borrow()) == 102)); let __decomp_4: Ptr = t.as_pointer(); - assert!((copies_0.with(|rc| *rc.borrow()) == (base_copies + 2))); - assert!(({ (*__decomp_4.upgrade().deref()).a.v } == 1)); - field!(field!(__decomp_4, a), v).write(50); - assert!(({ (*t.borrow()).a.v } == 50)); - let mut __decomp_5: Two = (*t.borrow()).clone(); - assert!((moves_1.with(|rc| *rc.borrow()) == (base_moves + 2))); - assert!(({ __decomp_5.a.v } == 1050)); - assert!(({ __decomp_5.b.v } == 1002)); - assert!(({ (*t.borrow()).a.v } == -1_i32)); - let mut before_copies: i32 = copies_0.with(|rc| *rc.borrow()); - let mut before_moves: i32 = moves_1.with(|rc| *rc.borrow()); - let mut __decomp_6: Two = ({ make_two_2() }); - assert!((copies_0.with(|rc| *rc.borrow()) == before_copies)); - assert!((moves_1.with(|rc| *rc.borrow()) == before_moves)); - assert!(({ __decomp_6.a.v } == 1)); + assert!((copies_0.with(|rc| *rc.borrow()) == ((*base_copies.borrow()) + 2))); + assert!(((*(*(*__decomp_4.upgrade().deref()).a.borrow()).v.borrow()) == 1)); + (*(*(*__decomp_4.upgrade().deref()).a.borrow()).v.borrow_mut()) = 50; + assert!(((*(*(*t.borrow()).a.borrow()).v.borrow()) == 50)); + let __decomp_5: Value = Rc::new(RefCell::new((*t.borrow()).clone())); + assert!((moves_1.with(|rc| *rc.borrow()) == ((*base_moves.borrow()) + 2))); + assert!(((*(*(*__decomp_5.borrow()).a.borrow()).v.borrow()) == 1050)); + assert!(((*(*(*__decomp_5.borrow()).b.borrow()).v.borrow()) == 1002)); + assert!(((*(*(*t.borrow()).a.borrow()).v.borrow()) == -1_i32)); + let before_copies: Value = Rc::new(RefCell::new(copies_0.with(|rc| *rc.borrow()))); + let before_moves: Value = Rc::new(RefCell::new(moves_1.with(|rc| *rc.borrow()))); + let __decomp_6: Value = Rc::new(RefCell::new(({ make_two_2() }))); + assert!((copies_0.with(|rc| *rc.borrow()) == (*before_copies.borrow()))); + assert!((moves_1.with(|rc| *rc.borrow()) == (*before_moves.borrow()))); + assert!(((*(*(*__decomp_6.borrow()).a.borrow()).v.borrow()) == 1)); let p: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new( Elem::new({ 7 }).try_into().expect("failed conversion"), @@ -100,14 +142,20 @@ fn main_0() -> i32 { Elem::new({ 8 }).try_into().expect("failed conversion"), )), ))); - before_copies = copies_0.with(|rc| *rc.borrow()); + (*before_copies.borrow_mut()) = copies_0.with(|rc| *rc.borrow()); let __decomp_7: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), ))); - assert!((copies_0.with(|rc| *rc.borrow()) == (before_copies + 2))); - assert!(({ (*x.upgrade().deref()).v } == ({ (*(*p.borrow()).0.borrow()).v } + 100))); - assert!(({ (*y.upgrade().deref()).v } == ({ (*(*p.borrow()).1.borrow()).v } + 100))); + let x: Ptr = ({ get_8((__decomp_7.as_pointer()).clone()) }); + let y: Ptr = ({ get_9((__decomp_7.as_pointer()).clone()) }); + assert!((copies_0.with(|rc| *rc.borrow()) == ((*before_copies.borrow()) + 2))); + assert!( + ((*(*x.upgrade().deref()).v.borrow()) == ((*(*(*p.borrow()).0.borrow()).v.borrow()) + 100)) + ); + assert!( + ((*(*y.upgrade().deref()).v.borrow()) == ((*(*(*p.borrow()).1.borrow()).v.borrow()) + 100)) + ); return 0; } pub fn __cpp2rust_init_globals() { diff --git a/tests/unit/out/refcount/structured_binding_pair.rs b/tests/unit/out/refcount/structured_binding_pair.rs index 42fce15c2..3ecd4285b 100644 --- a/tests/unit/out/refcount/structured_binding_pair.rs +++ b/tests/unit/out/refcount/structured_binding_pair.rs @@ -6,10 +6,15 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -pub fn make_std_pair_0(mut x: i32) -> (Value, Value) { +pub fn make_std_pair_0(x: i32) -> (Value, Value) { + let x: Value = Rc::new(RefCell::new(x)); return ( - Rc::new(RefCell::new(x.try_into().expect("failed conversion"))), - Rc::new(RefCell::new((x > 0).try_into().expect("failed conversion"))), + Rc::new(RefCell::new( + (*x.borrow()).try_into().expect("failed conversion"), + )), + Rc::new(RefCell::new( + ((*x.borrow()) > 0).try_into().expect("failed conversion"), + )), ); } pub fn main() { @@ -19,24 +24,31 @@ pub fn main() { fn main_0() -> i32 { let __decomp_1: Value<(Value, Value)> = Rc::new(RefCell::new(({ make_std_pair_0(5) }))); + let value: Ptr = ({ get_2((__decomp_1.as_pointer()).clone()) }); + let positive: Ptr = ({ get_3((__decomp_1.as_pointer()).clone()) }); assert!(((value.read()) == 5)); assert!(((positive.read()) as bool)); let p: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new(1.try_into().expect("failed conversion"))), Rc::new(RefCell::new(2.try_into().expect("failed conversion"))), ))); - let __decomp_2: Value<(Value, Value)> = Rc::new(RefCell::new(( + let __decomp_4: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), ))); + let a: Ptr = ({ get_5((__decomp_4.as_pointer()).clone()) }); + let b: Ptr = ({ get_6((__decomp_4.as_pointer()).clone()) }); a.write(10); assert!(((a.read()) == 10)); assert!(((b.read()) == 2)); assert!(((*(*p.borrow()).0.borrow()) == 1)); - let __decomp_3: Ptr<(Value, Value)> = p.as_pointer(); + let __decomp_7: Ptr<(Value, Value)> = p.as_pointer(); + let x: Ptr = ({ get_8((__decomp_7).clone()) }); + let y: Ptr = ({ get_9((__decomp_7).clone()) }); x.write(3); { - y.with_mut(|__v| *__v = *__v + 4) + let _ptr = y.clone(); + _ptr.write(_ptr.read() + 4) }; assert!(((*(*p.borrow()).0.borrow()) == 3)); assert!(((*(*p.borrow()).1.borrow()) == 6)); diff --git a/tests/unit/out/unsafe/structured_binding_element_ctor.rs b/tests/unit/out/unsafe/structured_binding_element_ctor.rs index b208fc58b..cf5e803b8 100644 --- a/tests/unit/out/unsafe/structured_binding_element_ctor.rs +++ b/tests/unit/out/unsafe/structured_binding_element_ctor.rs @@ -9,7 +9,7 @@ use std::rc::Rc; pub static mut copies_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); pub static mut moves_1: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); #[repr(C)] -#[derive(VaArg, FnPtrArg, MoveCtorUnsafe, Default)] +#[derive(VaArg, Default)] pub struct Elem { pub v: i32, } @@ -40,7 +40,7 @@ impl Clone for Elem { } } #[repr(C)] -#[derive(Clone, VaArg, FnPtrArg, Default)] +#[derive(Clone, VaArg, Default)] pub struct Two { pub a: Elem, pub b: Elem, @@ -88,6 +88,8 @@ unsafe fn main_0() -> i32 { let mut p: (Elem, Elem) = (Elem::new({ 7 }).into(), Elem::new({ 8 }).into()); before_copies = (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)); let mut __decomp_7: (Elem, Elem) = p.clone(); + let x: *mut Elem = (unsafe { get_8(&mut __decomp_7) }); + let y: *mut Elem = (unsafe { get_9(&mut __decomp_7) }); assert!( ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == ((before_copies) + (2))) ); diff --git a/tests/unit/out/unsafe/structured_binding_pair.rs b/tests/unit/out/unsafe/structured_binding_pair.rs index 3436d1671..b40bb3104 100644 --- a/tests/unit/out/unsafe/structured_binding_pair.rs +++ b/tests/unit/out/unsafe/structured_binding_pair.rs @@ -17,15 +17,21 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut __decomp_1: (i32, bool) = (unsafe { make_std_pair_0(5) }); + let value: *mut i32 = (unsafe { get_2(&mut __decomp_1) }); + let positive: *mut bool = (unsafe { get_3(&mut __decomp_1) }); assert!(((*value) == (5))); assert!(((*positive) as bool)); let mut p: (i32, i32) = (1.into(), 2.into()); - let mut __decomp_2: (i32, i32) = p.clone(); + let mut __decomp_4: (i32, i32) = p.clone(); + let a: *mut i32 = (unsafe { get_5(&mut __decomp_4) }); + let b: *mut i32 = (unsafe { get_6(&mut __decomp_4) }); (*a) = 10; assert!(((*a) == (10))); assert!(((*b) == (2))); assert!(((p.0) == (1))); - let __decomp_3: *mut (i32, i32) = &mut p; + let __decomp_7: *mut (i32, i32) = &mut p; + let x: *mut i32 = (unsafe { get_8(__decomp_7) }); + let y: *mut i32 = (unsafe { get_9(__decomp_7) }); (*x) = 3; (*y) += 4; assert!(((p.0) == (3))); From d738726bde8497daeb1cbbf470a880ac569fe0e6 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Tue, 29 Sep 2026 20:50:22 +0100 Subject: [PATCH 13/21] Mark no-compile the files that need get<> --- tests/unit/structured_binding_element_ctor.cpp | 1 + tests/unit/structured_binding_pair.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/unit/structured_binding_element_ctor.cpp b/tests/unit/structured_binding_element_ctor.cpp index c55d6c223..3cbe9ff10 100644 --- a/tests/unit/structured_binding_element_ctor.cpp +++ b/tests/unit/structured_binding_element_ctor.cpp @@ -1,4 +1,5 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++17 +// no-compile #include #include diff --git a/tests/unit/structured_binding_pair.cpp b/tests/unit/structured_binding_pair.cpp index 08f6dc0e5..cf4878616 100644 --- a/tests/unit/structured_binding_pair.cpp +++ b/tests/unit/structured_binding_pair.cpp @@ -1,4 +1,5 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++17 +// no-compile #include #include From 4caecdbba2851348e380ac006b916c8878ab2544 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Wed, 30 Sep 2026 21:58:51 +0100 Subject: [PATCH 14/21] Update tests --- .../refcount/structured_binding_copy_ctor.rs | 30 +++++---- .../refcount/structured_binding_move_ctor.rs | 64 +++++++++++++------ .../refcount/structured_binding_range_for.rs | 17 ++--- .../out/refcount/structured_binding_ref.rs | 3 +- .../refcount/structured_binding_trivial.rs | 26 ++++---- 5 files changed, 89 insertions(+), 51 deletions(-) diff --git a/tests/unit/out/refcount/structured_binding_copy_ctor.rs b/tests/unit/out/refcount/structured_binding_copy_ctor.rs index cf8c263fc..fe6e7c754 100644 --- a/tests/unit/out/refcount/structured_binding_copy_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_copy_ctor.rs @@ -18,16 +18,24 @@ pub struct Counted { pub y: i32, } impl Counted { - pub fn new(mut x: i32, mut y: i32) -> Self { - Self { x: x, y: y } + pub fn new(x: i32, y: i32) -> Self { + let x: Value = Rc::new(RefCell::new(x)); + let y: Value = Rc::new(RefCell::new(y)); + let __this: Value = Rc::new(RefCell::new(Self { + x: (*x.borrow()), + y: (*y.borrow()), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() } pub fn copy_from(other: Ptr) -> Self { - let __this: Counted = Self { + let __this: Value = Rc::new(RefCell::new(Self { x: (other.with(|__s| __s.x) * 2), y: (other.with(|__s| __s.y) * 2), - }; + })); + let this: Ptr = __this.as_pointer(); (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); - __this + Rc::try_unwrap(__this).ok().unwrap().into_inner() } } impl Clone for Counted { @@ -48,10 +56,10 @@ pub fn main() { } fn main_0() -> i32 { let s: Value = Rc::new(RefCell::new(Counted::new({ 1 }, { 2 }))); - let mut __decomp_2: Counted = Counted::copy_from({ s.as_pointer() }); + let __decomp_2: Value = Rc::new(RefCell::new(Counted::copy_from({ s.as_pointer() }))); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!((__decomp_2.x == 2)); - assert!((__decomp_2.y == 4)); + assert!(({ (*__decomp_2.borrow()).x } == 2)); + assert!(({ (*__decomp_2.borrow()).y } == 4)); let __decomp_3: Ptr = s.as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); assert!((__decomp_3.with(|__s| __s.x) == 1)); @@ -59,10 +67,10 @@ fn main_0() -> i32 { let __decomp_4: Ptr = s.as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); assert!((__decomp_4.with(|__s| __s.x) == 1)); - let mut __decomp_5: Counted = ({ make_counted_1() }); + let __decomp_5: Value = Rc::new(RefCell::new(({ make_counted_1() }))); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!((__decomp_5.x == 5)); - assert!((__decomp_5.y == 6)); + assert!(({ (*__decomp_5.borrow()).x } == 5)); + assert!(({ (*__decomp_5.borrow()).y } == 6)); return 0; } pub fn __cpp2rust_init_globals() { diff --git a/tests/unit/out/refcount/structured_binding_move_ctor.rs b/tests/unit/out/refcount/structured_binding_move_ctor.rs index 7e414bb44..f96a8f562 100644 --- a/tests/unit/out/refcount/structured_binding_move_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_move_ctor.rs @@ -12,7 +12,7 @@ thread_local!( thread_local!( pub static moves_1: Value = Rc::new(RefCell::new(0)); ); -#[derive(Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)] +#[derive(Record, ByteRepr, VaArg, FnPtrArg, Default)] #[byte_size(8)] pub struct Movable { #[offset(0)] @@ -21,26 +21,35 @@ pub struct Movable { pub y: i32, } impl Movable { - pub fn new(mut x: i32, mut y: i32) -> Self { - Self { x: x, y: y } + pub fn new(x: i32, y: i32) -> Self { + let x: Value = Rc::new(RefCell::new(x)); + let y: Value = Rc::new(RefCell::new(y)); + let __this: Value = Rc::new(RefCell::new(Self { + x: (*x.borrow()), + y: (*y.borrow()), + })); + let this: Ptr = __this.as_pointer(); + Rc::try_unwrap(__this).ok().unwrap().into_inner() } pub fn copy_from(other: Ptr) -> Self { - let __this: Movable = Self { + let __this: Value = Rc::new(RefCell::new(Self { x: other.with(|__s| __s.x), y: other.with(|__s| __s.y), - }; + })); + let this: Ptr = __this.as_pointer(); (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); - __this + Rc::try_unwrap(__this).ok().unwrap().into_inner() } pub fn move_from(other: Ptr) -> Self { - let __this: Movable = Self { + let __this: Value = Rc::new(RefCell::new(Self { x: other.with(|__s| __s.x), y: other.with(|__s| __s.y), - }; + })); + let this: Ptr = __this.as_pointer(); field!(other, x).write(0); field!(other, y).write(0); (*moves_1.with(Value::clone).borrow_mut()).prefix_inc(); - __this + Rc::try_unwrap(__this).ok().unwrap().into_inner() } } impl Clone for Movable { @@ -52,7 +61,7 @@ impl Clone for Movable { Movable::copy_from(__src.as_pointer()) } } -#[derive(DeepClone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[derive(Record, ByteRepr, VaArg, FnPtrArg, Default)] #[byte_size(48)] pub struct Holder { #[offset(0)] @@ -62,28 +71,47 @@ pub struct Holder { #[byte_size(24)] pub ys: Value>, } +impl Clone for Holder { + fn clone(&self) -> Self { + Self { + xs: Rc::new(RefCell::new((*self.xs.borrow()).clone())), + ys: Rc::new(RefCell::new((*self.ys.borrow()).clone())), + } + } +} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); } fn main_0() -> i32 { let m: Value = Rc::new(RefCell::new(Movable::new({ 3 }, { 4 }))); - let mut __decomp_2: Movable = Movable::move_from({ m.as_pointer() }); + let __decomp_2: Value = Rc::new(RefCell::new(Movable::move_from({ m.as_pointer() }))); assert!((moves_1.with(|rc| *rc.borrow()) == 1)); assert!((copies_0.with(|rc| *rc.borrow()) == 0)); - assert!((__decomp_2.x == 3)); - assert!((__decomp_2.y == 4)); + assert!(({ (*__decomp_2.borrow()).x } == 3)); + assert!(({ (*__decomp_2.borrow()).y } == 4)); assert!(({ (*m.borrow()).x } == 0)); assert!(({ (*m.borrow()).y } == 0)); let h: Value = Rc::new(RefCell::new(Holder { xs: Rc::new(RefCell::new(vec![1, 2, 3])), ys: Rc::new(RefCell::new(vec![4, 5])), })); - let mut __decomp_3: Holder = ({ HolderImpl::extract(&h.as_pointer()) }); - assert!(((*__decomp_3.xs.borrow()).len() == 3_usize)); - assert!(((*__decomp_3.ys.borrow()).len() == 2_usize)); - assert!(((elem!((__decomp_3.xs.as_pointer() as Ptr), 2_usize).read()) == 3)); - assert!(((elem!((__decomp_3.ys.as_pointer() as Ptr), 0_usize).read()) == 4)); + let __decomp_3: Value = + Rc::new(RefCell::new(({ HolderImpl::extract(&h.as_pointer()) }))); + assert!(((*{ (*__decomp_3.borrow()).xs.clone() }.borrow()).len() == 3_usize)); + assert!(((*{ (*__decomp_3.borrow()).ys.clone() }.borrow()).len() == 2_usize)); + assert!( + ((({ (*__decomp_3.borrow()).xs.clone() }.as_pointer() as Ptr) + .offset(2_usize) + .read()) + == 3) + ); + assert!( + ((({ (*__decomp_3.borrow()).ys.clone() }.as_pointer() as Ptr) + .offset(0_usize) + .read()) + == 4) + ); assert!((*{ (*h.borrow()).xs.clone() }.borrow()).is_empty()); assert!((*{ (*h.borrow()).ys.clone() }.borrow()).is_empty()); return 0; diff --git a/tests/unit/out/refcount/structured_binding_range_for.rs b/tests/unit/out/refcount/structured_binding_range_for.rs index 0abc1cdb8..2f84128b4 100644 --- a/tests/unit/out/refcount/structured_binding_range_for.rs +++ b/tests/unit/out/refcount/structured_binding_range_for.rs @@ -35,24 +35,25 @@ fn main_0() -> i32 { ]))); 'loop_: for mut __decomp_0 in arr.as_pointer() as Ptr { { - let __rhs = __decomp_0.with(|__s| __s.second); - field!(__decomp_0, first).with_mut(|__v| *__v = *__v + __rhs) + let _ptr = field!(__decomp_0, first); + _ptr.write(_ptr.read() + __decomp_0.with(|__s| __s.second)) }; } assert!(({ (*arr.borrow())[(0) as usize].first } == 3)); assert!(({ (*arr.borrow())[(2) as usize].first } == 11)); 'loop_: for mut __decomp_1 in arr.as_pointer() as Ptr { - let mut __decomp_1: Pair = __decomp_1.upgrade().deref().clone(); - __decomp_1.first = 0; - __decomp_1.second = 0; + let __decomp_1: Value = Rc::new(RefCell::new(__decomp_1.upgrade().deref().clone())); + (*__decomp_1.borrow_mut()).first = 0; + (*__decomp_1.borrow_mut()).second = 0; } assert!(({ (*arr.borrow())[(1) as usize].first } == 7)); assert!(({ (*arr.borrow())[(1) as usize].second } == 4)); - let mut sum: i32 = 0; + let sum: Value = Rc::new(RefCell::new(0)); 'loop_: for mut __decomp_2 in arr.as_pointer() as Ptr { - sum += (__decomp_2.with(|__s| __s.first) * __decomp_2.with(|__s| __s.second)); + (*sum.borrow_mut()) += + (__decomp_2.with(|__s| __s.first) * __decomp_2.with(|__s| __s.second)); } - assert!((sum == (((3 * 2) + (7 * 4)) + (11 * 6)))); + assert!(((*sum.borrow()) == (((3 * 2) + (7 * 4)) + (11 * 6)))); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_ref.rs b/tests/unit/out/refcount/structured_binding_ref.rs index ba4e6f54e..aecffdca0 100644 --- a/tests/unit/out/refcount/structured_binding_ref.rs +++ b/tests/unit/out/refcount/structured_binding_ref.rs @@ -35,7 +35,8 @@ fn main_0() -> i32 { field!(__decomp_2, a).write(11); field!(__decomp_2, b).write(true); { - field!(__decomp_2, c).with_mut(|__v| *__v = *__v + 1) + let _ptr = field!(__decomp_2, c); + _ptr.write(_ptr.read() + 1) }; assert!(({ (*t.borrow()).a } == 11)); assert!({ (*t.borrow()).b }); diff --git a/tests/unit/out/refcount/structured_binding_trivial.rs b/tests/unit/out/refcount/structured_binding_trivial.rs index 29c206941..e6533f533 100644 --- a/tests/unit/out/refcount/structured_binding_trivial.rs +++ b/tests/unit/out/refcount/structured_binding_trivial.rs @@ -19,23 +19,23 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let mut __decomp_0: Pair = Pair { + let __decomp_0: Value = Rc::new(RefCell::new(Pair { first: 1, second: 2, - }; - assert!((__decomp_0.first == 1)); - assert!((__decomp_0.second == 2)); - let mut p: Pair = Pair { + })); + assert!(({ (*__decomp_0.borrow()).first } == 1)); + assert!(({ (*__decomp_0.borrow()).second } == 2)); + let p: Value = Rc::new(RefCell::new(Pair { first: 10, second: 20, - }; - let mut __decomp_1: Pair = (p).clone(); - __decomp_1.first = 11; - __decomp_1.second += 1; - assert!((__decomp_1.first == 11)); - assert!((__decomp_1.second == 21)); - assert!((p.first == 10)); - assert!((p.second == 20)); + })); + let __decomp_1: Value = Rc::new(RefCell::new((*p.borrow()).clone())); + (*__decomp_1.borrow_mut()).first = 11; + (*__decomp_1.borrow_mut()).second += 1; + assert!(({ (*__decomp_1.borrow()).first } == 11)); + assert!(({ (*__decomp_1.borrow()).second } == 21)); + assert!(({ (*p.borrow()).first } == 10)); + assert!(({ (*p.borrow()).second } == 20)); return 0; } pub fn __cpp2rust_init_globals() {} From a8fea2a4b905aeb93898e1962d899ccd3119e5ea Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 2 Oct 2026 10:22:50 +0100 Subject: [PATCH 15/21] Update tests --- .../out/refcount/structured_binding_array.rs | 21 ++++++++------- .../refcount/structured_binding_move_ctor.rs | 26 ++++++++----------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/tests/unit/out/refcount/structured_binding_array.rs b/tests/unit/out/refcount/structured_binding_array.rs index c31977dc3..c253dd209 100644 --- a/tests/unit/out/refcount/structured_binding_array.rs +++ b/tests/unit/out/refcount/structured_binding_array.rs @@ -12,19 +12,20 @@ pub fn main() { } fn main_0() -> i32 { let arr: Value> = Rc::new(RefCell::new(Box::new([1, 2, 3]))); - let mut __decomp_0: [i32; 3] = Box::new(std::array::from_fn::<_, 3, _>(|__i: usize| { - (*arr.borrow())[(__i) as usize] - })); - __decomp_0[(0) as usize] = 10; - assert!((__decomp_0[(0) as usize] == 10)); - assert!((__decomp_0[(1) as usize] == 2)); - assert!((__decomp_0[(2) as usize] == 3)); + let __decomp_0: Value> = + Rc::new(RefCell::new(Box::new(std::array::from_fn::<_, 3, _>( + |__i: usize| (*arr.borrow())[(__i) as usize], + )))); + (*__decomp_0.borrow_mut())[(0) as usize] = 10; + assert!(((*__decomp_0.borrow())[(0) as usize] == 10)); + assert!(((*__decomp_0.borrow())[(1) as usize] == 2)); + assert!(((*__decomp_0.borrow())[(2) as usize] == 3)); assert!(((*arr.borrow())[(0) as usize] == 1)); - let __decomp_1: Ptr = arr.as_pointer(); + let __decomp_1: Ptr = (arr.as_pointer() as Ptr); elem!((__decomp_1), 0).write(7); { - let __rhs = (elem!((__decomp_1), 1).read()); - elem!((__decomp_1), 2).with_mut(|__v| *__v = *__v + __rhs) + let _ptr = elem!((__decomp_1), 2); + _ptr.write(_ptr.read() + (elem!((__decomp_1), 1).read())) }; assert!(((*arr.borrow())[(0) as usize] == 7)); assert!(((*arr.borrow())[(2) as usize] == 5)); diff --git a/tests/unit/out/refcount/structured_binding_move_ctor.rs b/tests/unit/out/refcount/structured_binding_move_ctor.rs index f96a8f562..52306f000 100644 --- a/tests/unit/out/refcount/structured_binding_move_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_move_ctor.rs @@ -61,7 +61,7 @@ impl Clone for Movable { Movable::copy_from(__src.as_pointer()) } } -#[derive(Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[derive(DeepClone, Record, ByteRepr, VaArg, FnPtrArg, Default)] #[byte_size(48)] pub struct Holder { #[offset(0)] @@ -71,14 +71,6 @@ pub struct Holder { #[byte_size(24)] pub ys: Value>, } -impl Clone for Holder { - fn clone(&self) -> Self { - Self { - xs: Rc::new(RefCell::new((*self.xs.borrow()).clone())), - ys: Rc::new(RefCell::new((*self.ys.borrow()).clone())), - } - } -} pub fn main() { __cpp2rust_init_globals(); std::process::exit(main_0()); @@ -101,15 +93,19 @@ fn main_0() -> i32 { assert!(((*{ (*__decomp_3.borrow()).xs.clone() }.borrow()).len() == 3_usize)); assert!(((*{ (*__decomp_3.borrow()).ys.clone() }.borrow()).len() == 2_usize)); assert!( - ((({ (*__decomp_3.borrow()).xs.clone() }.as_pointer() as Ptr) - .offset(2_usize) - .read()) + ((elem!( + ({ (*__decomp_3.borrow()).xs.as_pointer() } as Ptr), + 2_usize + ) + .read()) == 3) ); assert!( - ((({ (*__decomp_3.borrow()).ys.clone() }.as_pointer() as Ptr) - .offset(0_usize) - .read()) + ((elem!( + ({ (*__decomp_3.borrow()).ys.as_pointer() } as Ptr), + 0_usize + ) + .read()) == 4) ); assert!((*{ (*h.borrow()).xs.clone() }.borrow()).is_empty()); From 57d3ea60292a118f55442e924b0dbed3734e76ef Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 12 Oct 2026 09:31:53 +0100 Subject: [PATCH 16/21] Update tesst --- .../out/refcount/structured_binding_array.rs | 21 ++++--- .../refcount/structured_binding_copy_ctor.rs | 30 ++++------ .../refcount/structured_binding_move_ctor.rs | 58 ++++++------------- .../refcount/structured_binding_range_for.rs | 17 +++--- .../out/refcount/structured_binding_ref.rs | 3 +- .../refcount/structured_binding_trivial.rs | 26 ++++----- 6 files changed, 60 insertions(+), 95 deletions(-) diff --git a/tests/unit/out/refcount/structured_binding_array.rs b/tests/unit/out/refcount/structured_binding_array.rs index c253dd209..c31977dc3 100644 --- a/tests/unit/out/refcount/structured_binding_array.rs +++ b/tests/unit/out/refcount/structured_binding_array.rs @@ -12,20 +12,19 @@ pub fn main() { } fn main_0() -> i32 { let arr: Value> = Rc::new(RefCell::new(Box::new([1, 2, 3]))); - let __decomp_0: Value> = - Rc::new(RefCell::new(Box::new(std::array::from_fn::<_, 3, _>( - |__i: usize| (*arr.borrow())[(__i) as usize], - )))); - (*__decomp_0.borrow_mut())[(0) as usize] = 10; - assert!(((*__decomp_0.borrow())[(0) as usize] == 10)); - assert!(((*__decomp_0.borrow())[(1) as usize] == 2)); - assert!(((*__decomp_0.borrow())[(2) as usize] == 3)); + let mut __decomp_0: [i32; 3] = Box::new(std::array::from_fn::<_, 3, _>(|__i: usize| { + (*arr.borrow())[(__i) as usize] + })); + __decomp_0[(0) as usize] = 10; + assert!((__decomp_0[(0) as usize] == 10)); + assert!((__decomp_0[(1) as usize] == 2)); + assert!((__decomp_0[(2) as usize] == 3)); assert!(((*arr.borrow())[(0) as usize] == 1)); - let __decomp_1: Ptr = (arr.as_pointer() as Ptr); + let __decomp_1: Ptr = arr.as_pointer(); elem!((__decomp_1), 0).write(7); { - let _ptr = elem!((__decomp_1), 2); - _ptr.write(_ptr.read() + (elem!((__decomp_1), 1).read())) + let __rhs = (elem!((__decomp_1), 1).read()); + elem!((__decomp_1), 2).with_mut(|__v| *__v = *__v + __rhs) }; assert!(((*arr.borrow())[(0) as usize] == 7)); assert!(((*arr.borrow())[(2) as usize] == 5)); diff --git a/tests/unit/out/refcount/structured_binding_copy_ctor.rs b/tests/unit/out/refcount/structured_binding_copy_ctor.rs index fe6e7c754..cf8c263fc 100644 --- a/tests/unit/out/refcount/structured_binding_copy_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_copy_ctor.rs @@ -18,24 +18,16 @@ pub struct Counted { pub y: i32, } impl Counted { - pub fn new(x: i32, y: i32) -> Self { - let x: Value = Rc::new(RefCell::new(x)); - let y: Value = Rc::new(RefCell::new(y)); - let __this: Value = Rc::new(RefCell::new(Self { - x: (*x.borrow()), - y: (*y.borrow()), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + pub fn new(mut x: i32, mut y: i32) -> Self { + Self { x: x, y: y } } pub fn copy_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { + let __this: Counted = Self { x: (other.with(|__s| __s.x) * 2), y: (other.with(|__s| __s.y) * 2), - })); - let this: Ptr = __this.as_pointer(); + }; (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } } impl Clone for Counted { @@ -56,10 +48,10 @@ pub fn main() { } fn main_0() -> i32 { let s: Value = Rc::new(RefCell::new(Counted::new({ 1 }, { 2 }))); - let __decomp_2: Value = Rc::new(RefCell::new(Counted::copy_from({ s.as_pointer() }))); + let mut __decomp_2: Counted = Counted::copy_from({ s.as_pointer() }); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!(({ (*__decomp_2.borrow()).x } == 2)); - assert!(({ (*__decomp_2.borrow()).y } == 4)); + assert!((__decomp_2.x == 2)); + assert!((__decomp_2.y == 4)); let __decomp_3: Ptr = s.as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); assert!((__decomp_3.with(|__s| __s.x) == 1)); @@ -67,10 +59,10 @@ fn main_0() -> i32 { let __decomp_4: Ptr = s.as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); assert!((__decomp_4.with(|__s| __s.x) == 1)); - let __decomp_5: Value = Rc::new(RefCell::new(({ make_counted_1() }))); + let mut __decomp_5: Counted = ({ make_counted_1() }); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!(({ (*__decomp_5.borrow()).x } == 5)); - assert!(({ (*__decomp_5.borrow()).y } == 6)); + assert!((__decomp_5.x == 5)); + assert!((__decomp_5.y == 6)); return 0; } pub fn __cpp2rust_init_globals() { diff --git a/tests/unit/out/refcount/structured_binding_move_ctor.rs b/tests/unit/out/refcount/structured_binding_move_ctor.rs index 52306f000..7e414bb44 100644 --- a/tests/unit/out/refcount/structured_binding_move_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_move_ctor.rs @@ -12,7 +12,7 @@ thread_local!( thread_local!( pub static moves_1: Value = Rc::new(RefCell::new(0)); ); -#[derive(Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[derive(Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)] #[byte_size(8)] pub struct Movable { #[offset(0)] @@ -21,35 +21,26 @@ pub struct Movable { pub y: i32, } impl Movable { - pub fn new(x: i32, y: i32) -> Self { - let x: Value = Rc::new(RefCell::new(x)); - let y: Value = Rc::new(RefCell::new(y)); - let __this: Value = Rc::new(RefCell::new(Self { - x: (*x.borrow()), - y: (*y.borrow()), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + pub fn new(mut x: i32, mut y: i32) -> Self { + Self { x: x, y: y } } pub fn copy_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { + let __this: Movable = Self { x: other.with(|__s| __s.x), y: other.with(|__s| __s.y), - })); - let this: Ptr = __this.as_pointer(); + }; (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } pub fn move_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { + let __this: Movable = Self { x: other.with(|__s| __s.x), y: other.with(|__s| __s.y), - })); - let this: Ptr = __this.as_pointer(); + }; field!(other, x).write(0); field!(other, y).write(0); (*moves_1.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } } impl Clone for Movable { @@ -77,37 +68,22 @@ pub fn main() { } fn main_0() -> i32 { let m: Value = Rc::new(RefCell::new(Movable::new({ 3 }, { 4 }))); - let __decomp_2: Value = Rc::new(RefCell::new(Movable::move_from({ m.as_pointer() }))); + let mut __decomp_2: Movable = Movable::move_from({ m.as_pointer() }); assert!((moves_1.with(|rc| *rc.borrow()) == 1)); assert!((copies_0.with(|rc| *rc.borrow()) == 0)); - assert!(({ (*__decomp_2.borrow()).x } == 3)); - assert!(({ (*__decomp_2.borrow()).y } == 4)); + assert!((__decomp_2.x == 3)); + assert!((__decomp_2.y == 4)); assert!(({ (*m.borrow()).x } == 0)); assert!(({ (*m.borrow()).y } == 0)); let h: Value = Rc::new(RefCell::new(Holder { xs: Rc::new(RefCell::new(vec![1, 2, 3])), ys: Rc::new(RefCell::new(vec![4, 5])), })); - let __decomp_3: Value = - Rc::new(RefCell::new(({ HolderImpl::extract(&h.as_pointer()) }))); - assert!(((*{ (*__decomp_3.borrow()).xs.clone() }.borrow()).len() == 3_usize)); - assert!(((*{ (*__decomp_3.borrow()).ys.clone() }.borrow()).len() == 2_usize)); - assert!( - ((elem!( - ({ (*__decomp_3.borrow()).xs.as_pointer() } as Ptr), - 2_usize - ) - .read()) - == 3) - ); - assert!( - ((elem!( - ({ (*__decomp_3.borrow()).ys.as_pointer() } as Ptr), - 0_usize - ) - .read()) - == 4) - ); + let mut __decomp_3: Holder = ({ HolderImpl::extract(&h.as_pointer()) }); + assert!(((*__decomp_3.xs.borrow()).len() == 3_usize)); + assert!(((*__decomp_3.ys.borrow()).len() == 2_usize)); + assert!(((elem!((__decomp_3.xs.as_pointer() as Ptr), 2_usize).read()) == 3)); + assert!(((elem!((__decomp_3.ys.as_pointer() as Ptr), 0_usize).read()) == 4)); assert!((*{ (*h.borrow()).xs.clone() }.borrow()).is_empty()); assert!((*{ (*h.borrow()).ys.clone() }.borrow()).is_empty()); return 0; diff --git a/tests/unit/out/refcount/structured_binding_range_for.rs b/tests/unit/out/refcount/structured_binding_range_for.rs index 2f84128b4..0abc1cdb8 100644 --- a/tests/unit/out/refcount/structured_binding_range_for.rs +++ b/tests/unit/out/refcount/structured_binding_range_for.rs @@ -35,25 +35,24 @@ fn main_0() -> i32 { ]))); 'loop_: for mut __decomp_0 in arr.as_pointer() as Ptr { { - let _ptr = field!(__decomp_0, first); - _ptr.write(_ptr.read() + __decomp_0.with(|__s| __s.second)) + let __rhs = __decomp_0.with(|__s| __s.second); + field!(__decomp_0, first).with_mut(|__v| *__v = *__v + __rhs) }; } assert!(({ (*arr.borrow())[(0) as usize].first } == 3)); assert!(({ (*arr.borrow())[(2) as usize].first } == 11)); 'loop_: for mut __decomp_1 in arr.as_pointer() as Ptr { - let __decomp_1: Value = Rc::new(RefCell::new(__decomp_1.upgrade().deref().clone())); - (*__decomp_1.borrow_mut()).first = 0; - (*__decomp_1.borrow_mut()).second = 0; + let mut __decomp_1: Pair = __decomp_1.upgrade().deref().clone(); + __decomp_1.first = 0; + __decomp_1.second = 0; } assert!(({ (*arr.borrow())[(1) as usize].first } == 7)); assert!(({ (*arr.borrow())[(1) as usize].second } == 4)); - let sum: Value = Rc::new(RefCell::new(0)); + let mut sum: i32 = 0; 'loop_: for mut __decomp_2 in arr.as_pointer() as Ptr { - (*sum.borrow_mut()) += - (__decomp_2.with(|__s| __s.first) * __decomp_2.with(|__s| __s.second)); + sum += (__decomp_2.with(|__s| __s.first) * __decomp_2.with(|__s| __s.second)); } - assert!(((*sum.borrow()) == (((3 * 2) + (7 * 4)) + (11 * 6)))); + assert!((sum == (((3 * 2) + (7 * 4)) + (11 * 6)))); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/structured_binding_ref.rs b/tests/unit/out/refcount/structured_binding_ref.rs index aecffdca0..ba4e6f54e 100644 --- a/tests/unit/out/refcount/structured_binding_ref.rs +++ b/tests/unit/out/refcount/structured_binding_ref.rs @@ -35,8 +35,7 @@ fn main_0() -> i32 { field!(__decomp_2, a).write(11); field!(__decomp_2, b).write(true); { - let _ptr = field!(__decomp_2, c); - _ptr.write(_ptr.read() + 1) + field!(__decomp_2, c).with_mut(|__v| *__v = *__v + 1) }; assert!(({ (*t.borrow()).a } == 11)); assert!({ (*t.borrow()).b }); diff --git a/tests/unit/out/refcount/structured_binding_trivial.rs b/tests/unit/out/refcount/structured_binding_trivial.rs index e6533f533..29c206941 100644 --- a/tests/unit/out/refcount/structured_binding_trivial.rs +++ b/tests/unit/out/refcount/structured_binding_trivial.rs @@ -19,23 +19,23 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let __decomp_0: Value = Rc::new(RefCell::new(Pair { + let mut __decomp_0: Pair = Pair { first: 1, second: 2, - })); - assert!(({ (*__decomp_0.borrow()).first } == 1)); - assert!(({ (*__decomp_0.borrow()).second } == 2)); - let p: Value = Rc::new(RefCell::new(Pair { + }; + assert!((__decomp_0.first == 1)); + assert!((__decomp_0.second == 2)); + let mut p: Pair = Pair { first: 10, second: 20, - })); - let __decomp_1: Value = Rc::new(RefCell::new((*p.borrow()).clone())); - (*__decomp_1.borrow_mut()).first = 11; - (*__decomp_1.borrow_mut()).second += 1; - assert!(({ (*__decomp_1.borrow()).first } == 11)); - assert!(({ (*__decomp_1.borrow()).second } == 21)); - assert!(({ (*p.borrow()).first } == 10)); - assert!(({ (*p.borrow()).second } == 20)); + }; + let mut __decomp_1: Pair = (p).clone(); + __decomp_1.first = 11; + __decomp_1.second += 1; + assert!((__decomp_1.first == 11)); + assert!((__decomp_1.second == 21)); + assert!((p.first == 10)); + assert!((p.second == 20)); return 0; } pub fn __cpp2rust_init_globals() {} From b369ebc90423a5e8d966ccd45bb9b47cc8f0a3b7 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 12 Oct 2026 09:36:49 +0100 Subject: [PATCH 17/21] Box decompositions --- cpp2rust/converter/models/boxed_vars.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/cpp2rust/converter/models/boxed_vars.cpp b/cpp2rust/converter/models/boxed_vars.cpp index 467d53302..ee70f95f0 100644 --- a/cpp2rust/converter/models/boxed_vars.cpp +++ b/cpp2rust/converter/models/boxed_vars.cpp @@ -53,6 +53,7 @@ bool CanUnbox(const clang::VarDecl *decl) { } return (decl->isLocalVarDecl() || clang::isa(decl)) && !IsGlobalVar(decl) && !decl->isInitCapture() && + !clang::isa(decl) && !IsVaListType(decl->getType()); } From 30039a7c74798ffdf35631a8f8defc4c24676bb6 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 12 Oct 2026 09:37:29 +0100 Subject: [PATCH 18/21] Update tesst --- .../out/refcount/structured_binding_array.rs | 15 ++++----- .../refcount/structured_binding_copy_ctor.rs | 12 +++---- .../refcount/structured_binding_move_ctor.rs | 31 ++++++++++++++----- .../refcount/structured_binding_range_for.rs | 6 ++-- .../refcount/structured_binding_trivial.rs | 18 +++++------ 5 files changed, 49 insertions(+), 33 deletions(-) diff --git a/tests/unit/out/refcount/structured_binding_array.rs b/tests/unit/out/refcount/structured_binding_array.rs index c31977dc3..1d8f51014 100644 --- a/tests/unit/out/refcount/structured_binding_array.rs +++ b/tests/unit/out/refcount/structured_binding_array.rs @@ -12,13 +12,14 @@ pub fn main() { } fn main_0() -> i32 { let arr: Value> = Rc::new(RefCell::new(Box::new([1, 2, 3]))); - let mut __decomp_0: [i32; 3] = Box::new(std::array::from_fn::<_, 3, _>(|__i: usize| { - (*arr.borrow())[(__i) as usize] - })); - __decomp_0[(0) as usize] = 10; - assert!((__decomp_0[(0) as usize] == 10)); - assert!((__decomp_0[(1) as usize] == 2)); - assert!((__decomp_0[(2) as usize] == 3)); + let __decomp_0: Value> = + Rc::new(RefCell::new(Box::new(std::array::from_fn::<_, 3, _>( + |__i: usize| (*arr.borrow())[(__i) as usize], + )))); + (*__decomp_0.borrow_mut())[(0) as usize] = 10; + assert!(((*__decomp_0.borrow())[(0) as usize] == 10)); + assert!(((*__decomp_0.borrow())[(1) as usize] == 2)); + assert!(((*__decomp_0.borrow())[(2) as usize] == 3)); assert!(((*arr.borrow())[(0) as usize] == 1)); let __decomp_1: Ptr = arr.as_pointer(); elem!((__decomp_1), 0).write(7); diff --git a/tests/unit/out/refcount/structured_binding_copy_ctor.rs b/tests/unit/out/refcount/structured_binding_copy_ctor.rs index cf8c263fc..41d029a1f 100644 --- a/tests/unit/out/refcount/structured_binding_copy_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_copy_ctor.rs @@ -48,10 +48,10 @@ pub fn main() { } fn main_0() -> i32 { let s: Value = Rc::new(RefCell::new(Counted::new({ 1 }, { 2 }))); - let mut __decomp_2: Counted = Counted::copy_from({ s.as_pointer() }); + let __decomp_2: Value = Rc::new(RefCell::new(Counted::copy_from({ s.as_pointer() }))); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!((__decomp_2.x == 2)); - assert!((__decomp_2.y == 4)); + assert!(({ (*__decomp_2.borrow()).x } == 2)); + assert!(({ (*__decomp_2.borrow()).y } == 4)); let __decomp_3: Ptr = s.as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); assert!((__decomp_3.with(|__s| __s.x) == 1)); @@ -59,10 +59,10 @@ fn main_0() -> i32 { let __decomp_4: Ptr = s.as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); assert!((__decomp_4.with(|__s| __s.x) == 1)); - let mut __decomp_5: Counted = ({ make_counted_1() }); + let __decomp_5: Value = Rc::new(RefCell::new(({ make_counted_1() }))); assert!((copies_0.with(|rc| *rc.borrow()) == 1)); - assert!((__decomp_5.x == 5)); - assert!((__decomp_5.y == 6)); + assert!(({ (*__decomp_5.borrow()).x } == 5)); + assert!(({ (*__decomp_5.borrow()).y } == 6)); return 0; } pub fn __cpp2rust_init_globals() { diff --git a/tests/unit/out/refcount/structured_binding_move_ctor.rs b/tests/unit/out/refcount/structured_binding_move_ctor.rs index 7e414bb44..2686fc4ef 100644 --- a/tests/unit/out/refcount/structured_binding_move_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_move_ctor.rs @@ -68,22 +68,37 @@ pub fn main() { } fn main_0() -> i32 { let m: Value = Rc::new(RefCell::new(Movable::new({ 3 }, { 4 }))); - let mut __decomp_2: Movable = Movable::move_from({ m.as_pointer() }); + let __decomp_2: Value = Rc::new(RefCell::new(Movable::move_from({ m.as_pointer() }))); assert!((moves_1.with(|rc| *rc.borrow()) == 1)); assert!((copies_0.with(|rc| *rc.borrow()) == 0)); - assert!((__decomp_2.x == 3)); - assert!((__decomp_2.y == 4)); + assert!(({ (*__decomp_2.borrow()).x } == 3)); + assert!(({ (*__decomp_2.borrow()).y } == 4)); assert!(({ (*m.borrow()).x } == 0)); assert!(({ (*m.borrow()).y } == 0)); let h: Value = Rc::new(RefCell::new(Holder { xs: Rc::new(RefCell::new(vec![1, 2, 3])), ys: Rc::new(RefCell::new(vec![4, 5])), })); - let mut __decomp_3: Holder = ({ HolderImpl::extract(&h.as_pointer()) }); - assert!(((*__decomp_3.xs.borrow()).len() == 3_usize)); - assert!(((*__decomp_3.ys.borrow()).len() == 2_usize)); - assert!(((elem!((__decomp_3.xs.as_pointer() as Ptr), 2_usize).read()) == 3)); - assert!(((elem!((__decomp_3.ys.as_pointer() as Ptr), 0_usize).read()) == 4)); + let __decomp_3: Value = + Rc::new(RefCell::new(({ HolderImpl::extract(&h.as_pointer()) }))); + assert!(((*{ (*__decomp_3.borrow()).xs.clone() }.borrow()).len() == 3_usize)); + assert!(((*{ (*__decomp_3.borrow()).ys.clone() }.borrow()).len() == 2_usize)); + assert!( + ((elem!( + ({ (*__decomp_3.borrow()).xs.as_pointer() } as Ptr), + 2_usize + ) + .read()) + == 3) + ); + assert!( + ((elem!( + ({ (*__decomp_3.borrow()).ys.as_pointer() } as Ptr), + 0_usize + ) + .read()) + == 4) + ); assert!((*{ (*h.borrow()).xs.clone() }.borrow()).is_empty()); assert!((*{ (*h.borrow()).ys.clone() }.borrow()).is_empty()); return 0; diff --git a/tests/unit/out/refcount/structured_binding_range_for.rs b/tests/unit/out/refcount/structured_binding_range_for.rs index 0abc1cdb8..7005eb29c 100644 --- a/tests/unit/out/refcount/structured_binding_range_for.rs +++ b/tests/unit/out/refcount/structured_binding_range_for.rs @@ -42,9 +42,9 @@ fn main_0() -> i32 { assert!(({ (*arr.borrow())[(0) as usize].first } == 3)); assert!(({ (*arr.borrow())[(2) as usize].first } == 11)); 'loop_: for mut __decomp_1 in arr.as_pointer() as Ptr { - let mut __decomp_1: Pair = __decomp_1.upgrade().deref().clone(); - __decomp_1.first = 0; - __decomp_1.second = 0; + let __decomp_1: Value = Rc::new(RefCell::new(__decomp_1.upgrade().deref().clone())); + (*__decomp_1.borrow_mut()).first = 0; + (*__decomp_1.borrow_mut()).second = 0; } assert!(({ (*arr.borrow())[(1) as usize].first } == 7)); assert!(({ (*arr.borrow())[(1) as usize].second } == 4)); diff --git a/tests/unit/out/refcount/structured_binding_trivial.rs b/tests/unit/out/refcount/structured_binding_trivial.rs index 29c206941..a968d0cb2 100644 --- a/tests/unit/out/refcount/structured_binding_trivial.rs +++ b/tests/unit/out/refcount/structured_binding_trivial.rs @@ -19,21 +19,21 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let mut __decomp_0: Pair = Pair { + let __decomp_0: Value = Rc::new(RefCell::new(Pair { first: 1, second: 2, - }; - assert!((__decomp_0.first == 1)); - assert!((__decomp_0.second == 2)); + })); + assert!(({ (*__decomp_0.borrow()).first } == 1)); + assert!(({ (*__decomp_0.borrow()).second } == 2)); let mut p: Pair = Pair { first: 10, second: 20, }; - let mut __decomp_1: Pair = (p).clone(); - __decomp_1.first = 11; - __decomp_1.second += 1; - assert!((__decomp_1.first == 11)); - assert!((__decomp_1.second == 21)); + let __decomp_1: Value = Rc::new(RefCell::new((p).clone())); + (*__decomp_1.borrow_mut()).first = 11; + (*__decomp_1.borrow_mut()).second += 1; + assert!(({ (*__decomp_1.borrow()).first } == 11)); + assert!(({ (*__decomp_1.borrow()).second } == 21)); assert!((p.first == 10)); assert!((p.second == 20)); return 0; From 08418af3127e6f3e5699865196d7c3d5445ebfcd Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 10:52:46 +0100 Subject: [PATCH 19/21] Update tests --- .../structured_binding_element_ctor.rs | 150 ++++++------------ .../out/refcount/structured_binding_pair.rs | 26 ++- .../unsafe/structured_binding_element_ctor.rs | 4 +- .../out/unsafe/structured_binding_pair.rs | 4 +- .../unit/structured_binding_element_ctor.cpp | 1 - tests/unit/structured_binding_pair.cpp | 1 - 6 files changed, 66 insertions(+), 120 deletions(-) diff --git a/tests/unit/out/refcount/structured_binding_element_ctor.rs b/tests/unit/out/refcount/structured_binding_element_ctor.rs index 6f0054430..d6d81fd61 100644 --- a/tests/unit/out/refcount/structured_binding_element_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_element_ctor.rs @@ -12,39 +12,30 @@ thread_local!( thread_local!( pub static moves_1: Value = Rc::new(RefCell::new(0)); ); -#[derive(VaArg, FnPtrArg, Default)] +#[derive(Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)] +#[byte_size(4)] pub struct Elem { - pub v: Value, + #[offset(0)] + pub v: i32, } impl Elem { - pub fn new(v: i32) -> Self { - let v: Value = Rc::new(RefCell::new(v)); - let __this: Value = Rc::new(RefCell::new(Self { - v: Rc::new(RefCell::new((*v.borrow()))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + pub fn new(mut v: i32) -> Self { + Self { v: v } } pub fn copy_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - v: Rc::new(RefCell::new( - ((*(*other.upgrade().deref()).v.borrow()) + 100), - )), - })); - let this: Ptr = __this.as_pointer(); + let __this: Elem = Self { + v: (other.with(|__s| __s.v) + 100), + }; (*copies_0.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } pub fn move_from(other: Ptr) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - v: Rc::new(RefCell::new( - ((*(*other.upgrade().deref()).v.borrow()) + 1000), - )), - })); - let this: Ptr = __this.as_pointer(); - (*(*other.upgrade().deref()).v.borrow_mut()) = -1_i32; + let __this: Elem = Self { + v: (other.with(|__s| __s.v) + 1000), + }; + field!(other, v).write(-1_i32); (*moves_1.with(Value::clone).borrow_mut()).prefix_inc(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() + __this } } impl Clone for Elem { @@ -53,53 +44,20 @@ impl Clone for Elem { Elem::copy_from(__src.as_pointer()) } } -impl ByteRepr for Elem { - 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(VaArg, FnPtrArg, Default)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[byte_size(8)] pub struct Two { - pub a: Value, - pub b: Value, -} -impl Clone for Two { - fn clone(&self) -> Self { - let __this: Value = Rc::new(RefCell::new(Self { - a: Rc::new(RefCell::new(Elem::copy_from({ self.a.as_pointer() }))), - b: Rc::new(RefCell::new(Elem::copy_from({ self.b.as_pointer() }))), - })); - let this: Ptr = __this.as_pointer(); - Rc::try_unwrap(__this).ok().unwrap().into_inner() - } -} -impl ByteRepr for Two { - fn byte_size() -> usize { - 8 - } - fn to_bytes(&self, buf: &mut [u8]) { - (*self.a.borrow()).to_bytes(&mut buf[0..4]); - (*self.b.borrow()).to_bytes(&mut buf[4..8]); - } - fn from_bytes(buf: &[u8]) -> Self { - Self { - a: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), - b: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), - } - } + #[offset(0)] + #[byte_size(4)] + pub a: Elem, + #[offset(4)] + #[byte_size(4)] + pub b: Elem, } pub fn make_two_2() -> Two { return Two { - a: Rc::new(RefCell::new(Elem::new({ 1 }))), - b: Rc::new(RefCell::new(Elem::new({ 2 }))), + a: Elem::new({ 1 }), + b: Elem::new({ 2 }), }; } pub fn main() { @@ -108,32 +66,32 @@ pub fn main() { } fn main_0() -> i32 { let t: Value = Rc::new(RefCell::new(Two { - a: Rc::new(RefCell::new(Elem::new({ 1 }))), - b: Rc::new(RefCell::new(Elem::new({ 2 }))), + a: Elem::new({ 1 }), + b: Elem::new({ 2 }), })); - let base_copies: Value = Rc::new(RefCell::new(copies_0.with(|rc| *rc.borrow()))); - let base_moves: Value = Rc::new(RefCell::new(moves_1.with(|rc| *rc.borrow()))); + let mut base_copies: i32 = copies_0.with(|rc| *rc.borrow()); + let mut base_moves: i32 = moves_1.with(|rc| *rc.borrow()); let __decomp_3: Value = Rc::new(RefCell::new((*t.borrow()).clone())); - assert!((copies_0.with(|rc| *rc.borrow()) == ((*base_copies.borrow()) + 2))); - assert!((moves_1.with(|rc| *rc.borrow()) == (*base_moves.borrow()))); - assert!(((*(*(*__decomp_3.borrow()).a.borrow()).v.borrow()) == 101)); - assert!(((*(*(*__decomp_3.borrow()).b.borrow()).v.borrow()) == 102)); + assert!((copies_0.with(|rc| *rc.borrow()) == (base_copies + 2))); + assert!((moves_1.with(|rc| *rc.borrow()) == base_moves)); + assert!(({ (*__decomp_3.borrow()).a.v } == 101)); + assert!(({ (*__decomp_3.borrow()).b.v } == 102)); let __decomp_4: Ptr = t.as_pointer(); - assert!((copies_0.with(|rc| *rc.borrow()) == ((*base_copies.borrow()) + 2))); - assert!(((*(*(*__decomp_4.upgrade().deref()).a.borrow()).v.borrow()) == 1)); - (*(*(*__decomp_4.upgrade().deref()).a.borrow()).v.borrow_mut()) = 50; - assert!(((*(*(*t.borrow()).a.borrow()).v.borrow()) == 50)); + assert!((copies_0.with(|rc| *rc.borrow()) == (base_copies + 2))); + assert!(({ (*__decomp_4.upgrade().deref()).a.v } == 1)); + field!(field!(__decomp_4, a), v).write(50); + assert!(({ (*t.borrow()).a.v } == 50)); let __decomp_5: Value = Rc::new(RefCell::new((*t.borrow()).clone())); - assert!((moves_1.with(|rc| *rc.borrow()) == ((*base_moves.borrow()) + 2))); - assert!(((*(*(*__decomp_5.borrow()).a.borrow()).v.borrow()) == 1050)); - assert!(((*(*(*__decomp_5.borrow()).b.borrow()).v.borrow()) == 1002)); - assert!(((*(*(*t.borrow()).a.borrow()).v.borrow()) == -1_i32)); - let before_copies: Value = Rc::new(RefCell::new(copies_0.with(|rc| *rc.borrow()))); - let before_moves: Value = Rc::new(RefCell::new(moves_1.with(|rc| *rc.borrow()))); + assert!((moves_1.with(|rc| *rc.borrow()) == (base_moves + 2))); + assert!(({ (*__decomp_5.borrow()).a.v } == 1050)); + assert!(({ (*__decomp_5.borrow()).b.v } == 1002)); + assert!(({ (*t.borrow()).a.v } == -1_i32)); + let mut before_copies: i32 = copies_0.with(|rc| *rc.borrow()); + let mut before_moves: i32 = moves_1.with(|rc| *rc.borrow()); let __decomp_6: Value = Rc::new(RefCell::new(({ make_two_2() }))); - assert!((copies_0.with(|rc| *rc.borrow()) == (*before_copies.borrow()))); - assert!((moves_1.with(|rc| *rc.borrow()) == (*before_moves.borrow()))); - assert!(((*(*(*__decomp_6.borrow()).a.borrow()).v.borrow()) == 1)); + assert!((copies_0.with(|rc| *rc.borrow()) == before_copies)); + assert!((moves_1.with(|rc| *rc.borrow()) == before_moves)); + assert!(({ (*__decomp_6.borrow()).a.v } == 1)); let p: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new( Elem::new({ 7 }).try_into().expect("failed conversion"), @@ -142,20 +100,16 @@ fn main_0() -> i32 { Elem::new({ 8 }).try_into().expect("failed conversion"), )), ))); - (*before_copies.borrow_mut()) = copies_0.with(|rc| *rc.borrow()); + before_copies = copies_0.with(|rc| *rc.borrow()); let __decomp_7: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), ))); - let x: Ptr = ({ get_8((__decomp_7.as_pointer()).clone()) }); - let y: Ptr = ({ get_9((__decomp_7.as_pointer()).clone()) }); - assert!((copies_0.with(|rc| *rc.borrow()) == ((*before_copies.borrow()) + 2))); - assert!( - ((*(*x.upgrade().deref()).v.borrow()) == ((*(*(*p.borrow()).0.borrow()).v.borrow()) + 100)) - ); - assert!( - ((*(*y.upgrade().deref()).v.borrow()) == ((*(*(*p.borrow()).1.borrow()).v.borrow()) + 100)) - ); + let x: Ptr = ({ get_8(__decomp_7.as_pointer()) }); + let y: Ptr = ({ get_9(__decomp_7.as_pointer()) }); + assert!((copies_0.with(|rc| *rc.borrow()) == (before_copies + 2))); + assert!(({ (*x.upgrade().deref()).v } == ({ (*(*p.borrow()).0.borrow()).v } + 100))); + assert!(({ (*y.upgrade().deref()).v } == ({ (*(*p.borrow()).1.borrow()).v } + 100))); return 0; } pub fn __cpp2rust_init_globals() { diff --git a/tests/unit/out/refcount/structured_binding_pair.rs b/tests/unit/out/refcount/structured_binding_pair.rs index 3ecd4285b..a0f887083 100644 --- a/tests/unit/out/refcount/structured_binding_pair.rs +++ b/tests/unit/out/refcount/structured_binding_pair.rs @@ -6,15 +6,10 @@ use std::io::prelude::*; use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; -pub fn make_std_pair_0(x: i32) -> (Value, Value) { - let x: Value = Rc::new(RefCell::new(x)); +pub fn make_std_pair_0(mut x: i32) -> (Value, Value) { return ( - Rc::new(RefCell::new( - (*x.borrow()).try_into().expect("failed conversion"), - )), - Rc::new(RefCell::new( - ((*x.borrow()) > 0).try_into().expect("failed conversion"), - )), + Rc::new(RefCell::new(x.try_into().expect("failed conversion"))), + Rc::new(RefCell::new((x > 0).try_into().expect("failed conversion"))), ); } pub fn main() { @@ -24,8 +19,8 @@ pub fn main() { fn main_0() -> i32 { let __decomp_1: Value<(Value, Value)> = Rc::new(RefCell::new(({ make_std_pair_0(5) }))); - let value: Ptr = ({ get_2((__decomp_1.as_pointer()).clone()) }); - let positive: Ptr = ({ get_3((__decomp_1.as_pointer()).clone()) }); + let value: Ptr = ({ get_2(__decomp_1.as_pointer()) }); + let positive: Ptr = ({ get_3(__decomp_1.as_pointer()) }); assert!(((value.read()) == 5)); assert!(((positive.read()) as bool)); let p: Value<(Value, Value)> = Rc::new(RefCell::new(( @@ -36,19 +31,18 @@ fn main_0() -> i32 { Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), ))); - let a: Ptr = ({ get_5((__decomp_4.as_pointer()).clone()) }); - let b: Ptr = ({ get_6((__decomp_4.as_pointer()).clone()) }); + let a: Ptr = ({ get_5(__decomp_4.as_pointer()) }); + let b: Ptr = ({ get_6(__decomp_4.as_pointer()) }); a.write(10); assert!(((a.read()) == 10)); assert!(((b.read()) == 2)); assert!(((*(*p.borrow()).0.borrow()) == 1)); let __decomp_7: Ptr<(Value, Value)> = p.as_pointer(); - let x: Ptr = ({ get_8((__decomp_7).clone()) }); - let y: Ptr = ({ get_9((__decomp_7).clone()) }); + let x: Ptr = (*__decomp_7.upgrade().deref()).0.as_pointer(); + let y: Ptr = (*__decomp_7.upgrade().deref()).1.as_pointer(); x.write(3); { - let _ptr = y.clone(); - _ptr.write(_ptr.read() + 4) + y.with_mut(|__v| *__v = *__v + 4) }; assert!(((*(*p.borrow()).0.borrow()) == 3)); assert!(((*(*p.borrow()).1.borrow()) == 6)); diff --git a/tests/unit/out/unsafe/structured_binding_element_ctor.rs b/tests/unit/out/unsafe/structured_binding_element_ctor.rs index cf5e803b8..6df3360f8 100644 --- a/tests/unit/out/unsafe/structured_binding_element_ctor.rs +++ b/tests/unit/out/unsafe/structured_binding_element_ctor.rs @@ -9,7 +9,7 @@ use std::rc::Rc; pub static mut copies_0: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); pub static mut moves_1: std::cell::LazyCell = std::cell::LazyCell::new(|| unsafe { 0 }); #[repr(C)] -#[derive(VaArg, Default)] +#[derive(VaArg, FnPtrArg, MoveCtorUnsafe, Default)] pub struct Elem { pub v: i32, } @@ -40,7 +40,7 @@ impl Clone for Elem { } } #[repr(C)] -#[derive(Clone, VaArg, Default)] +#[derive(Clone, VaArg, FnPtrArg, Default)] pub struct Two { pub a: Elem, pub b: Elem, diff --git a/tests/unit/out/unsafe/structured_binding_pair.rs b/tests/unit/out/unsafe/structured_binding_pair.rs index b40bb3104..88a1a0a40 100644 --- a/tests/unit/out/unsafe/structured_binding_pair.rs +++ b/tests/unit/out/unsafe/structured_binding_pair.rs @@ -30,8 +30,8 @@ unsafe fn main_0() -> i32 { assert!(((*b) == (2))); assert!(((p.0) == (1))); let __decomp_7: *mut (i32, i32) = &mut p; - let x: *mut i32 = (unsafe { get_8(__decomp_7) }); - let y: *mut i32 = (unsafe { get_9(__decomp_7) }); + let x: *mut i32 = &mut (*__decomp_7).0; + let y: *mut i32 = &mut (*__decomp_7).1; (*x) = 3; (*y) += 4; assert!(((p.0) == (3))); diff --git a/tests/unit/structured_binding_element_ctor.cpp b/tests/unit/structured_binding_element_ctor.cpp index 3cbe9ff10..c55d6c223 100644 --- a/tests/unit/structured_binding_element_ctor.cpp +++ b/tests/unit/structured_binding_element_ctor.cpp @@ -1,5 +1,4 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++17 -// no-compile #include #include diff --git a/tests/unit/structured_binding_pair.cpp b/tests/unit/structured_binding_pair.cpp index cf4878616..08f6dc0e5 100644 --- a/tests/unit/structured_binding_pair.cpp +++ b/tests/unit/structured_binding_pair.cpp @@ -1,5 +1,4 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++17 -// no-compile #include #include From 62b87afe7a106c50bfa3914bf35942b40754ceb6 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 11:03:53 +0100 Subject: [PATCH 20/21] Add more get overloads --- rules/pair/src.cpp | 8 ++++++++ rules/pair/tgt_refcount.rs | 8 ++++++++ rules/pair/tgt_unsafe.rs | 8 ++++++++ .../refcount/structured_binding_element_ctor.rs | 4 ++-- .../unit/out/refcount/structured_binding_pair.rs | 16 ++++++++-------- .../unsafe/structured_binding_element_ctor.rs | 4 ++-- tests/unit/out/unsafe/structured_binding_pair.rs | 16 ++++++++-------- 7 files changed, 44 insertions(+), 20 deletions(-) diff --git a/rules/pair/src.cpp b/rules/pair/src.cpp index 508e96f77..b81a3c3ac 100644 --- a/rules/pair/src.cpp +++ b/rules/pair/src.cpp @@ -64,3 +64,11 @@ template const T1 &f19(const std::pair &a0) { template const T2 &f20(const std::pair &a0) { return std::get<1>(a0); } + +template T1 &&f21(std::pair &&a0) { + return std::get<0>(std::move(a0)); +} + +template T2 &&f22(std::pair &&a0) { + return std::get<1>(std::move(a0)); +} diff --git a/rules/pair/tgt_refcount.rs b/rules/pair/tgt_refcount.rs index 5cfff3711..07757ab39 100644 --- a/rules/pair/tgt_refcount.rs +++ b/rules/pair/tgt_refcount.rs @@ -84,3 +84,11 @@ fn f19(a0: (Value, Value)) -> Ptr { fn f20(a0: (Value, Value)) -> Ptr { a0.1.as_pointer() } + +fn f21(a0: (Value, Value)) -> Ptr { + a0.0.as_pointer() +} + +fn f22(a0: (Value, Value)) -> Ptr { + a0.1.as_pointer() +} diff --git a/rules/pair/tgt_unsafe.rs b/rules/pair/tgt_unsafe.rs index d679f6594..c9c5bcff5 100644 --- a/rules/pair/tgt_unsafe.rs +++ b/rules/pair/tgt_unsafe.rs @@ -53,3 +53,11 @@ unsafe fn f19(a0: &(T1, T2)) -> *const T1 { unsafe fn f20(a0: &(T1, T2)) -> *const T2 { &a0.1 } + +unsafe fn f21(a0: &mut (T1, T2)) -> *mut T1 { + &mut a0.0 +} + +unsafe fn f22(a0: &mut (T1, T2)) -> *mut T2 { + &mut a0.1 +} diff --git a/tests/unit/out/refcount/structured_binding_element_ctor.rs b/tests/unit/out/refcount/structured_binding_element_ctor.rs index d6d81fd61..63f73f3e6 100644 --- a/tests/unit/out/refcount/structured_binding_element_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_element_ctor.rs @@ -105,8 +105,8 @@ fn main_0() -> i32 { Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), ))); - let x: Ptr = ({ get_8(__decomp_7.as_pointer()) }); - let y: Ptr = ({ get_9(__decomp_7.as_pointer()) }); + let x: Ptr = (*__decomp_7.borrow()).0.as_pointer(); + let y: Ptr = (*__decomp_7.borrow()).1.as_pointer(); assert!((copies_0.with(|rc| *rc.borrow()) == (before_copies + 2))); assert!(({ (*x.upgrade().deref()).v } == ({ (*(*p.borrow()).0.borrow()).v } + 100))); assert!(({ (*y.upgrade().deref()).v } == ({ (*(*p.borrow()).1.borrow()).v } + 100))); diff --git a/tests/unit/out/refcount/structured_binding_pair.rs b/tests/unit/out/refcount/structured_binding_pair.rs index a0f887083..c00bd9f9a 100644 --- a/tests/unit/out/refcount/structured_binding_pair.rs +++ b/tests/unit/out/refcount/structured_binding_pair.rs @@ -19,27 +19,27 @@ pub fn main() { fn main_0() -> i32 { let __decomp_1: Value<(Value, Value)> = Rc::new(RefCell::new(({ make_std_pair_0(5) }))); - let value: Ptr = ({ get_2(__decomp_1.as_pointer()) }); - let positive: Ptr = ({ get_3(__decomp_1.as_pointer()) }); + let value: Ptr = (*__decomp_1.borrow()).0.as_pointer(); + let positive: Ptr = (*__decomp_1.borrow()).1.as_pointer(); assert!(((value.read()) == 5)); assert!(((positive.read()) as bool)); let p: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new(1.try_into().expect("failed conversion"))), Rc::new(RefCell::new(2.try_into().expect("failed conversion"))), ))); - let __decomp_4: Value<(Value, Value)> = Rc::new(RefCell::new(( + let __decomp_2: Value<(Value, Value)> = Rc::new(RefCell::new(( Rc::new(RefCell::new((*p.borrow()).0.borrow().clone())), Rc::new(RefCell::new((*p.borrow()).1.borrow().clone())), ))); - let a: Ptr = ({ get_5(__decomp_4.as_pointer()) }); - let b: Ptr = ({ get_6(__decomp_4.as_pointer()) }); + let a: Ptr = (*__decomp_2.borrow()).0.as_pointer(); + let b: Ptr = (*__decomp_2.borrow()).1.as_pointer(); a.write(10); assert!(((a.read()) == 10)); assert!(((b.read()) == 2)); assert!(((*(*p.borrow()).0.borrow()) == 1)); - let __decomp_7: Ptr<(Value, Value)> = p.as_pointer(); - let x: Ptr = (*__decomp_7.upgrade().deref()).0.as_pointer(); - let y: Ptr = (*__decomp_7.upgrade().deref()).1.as_pointer(); + let __decomp_3: Ptr<(Value, Value)> = p.as_pointer(); + let x: Ptr = (*__decomp_3.upgrade().deref()).0.as_pointer(); + let y: Ptr = (*__decomp_3.upgrade().deref()).1.as_pointer(); x.write(3); { y.with_mut(|__v| *__v = *__v + 4) diff --git a/tests/unit/out/unsafe/structured_binding_element_ctor.rs b/tests/unit/out/unsafe/structured_binding_element_ctor.rs index 6df3360f8..dd1efe3bb 100644 --- a/tests/unit/out/unsafe/structured_binding_element_ctor.rs +++ b/tests/unit/out/unsafe/structured_binding_element_ctor.rs @@ -88,8 +88,8 @@ unsafe fn main_0() -> i32 { let mut p: (Elem, Elem) = (Elem::new({ 7 }).into(), Elem::new({ 8 }).into()); before_copies = (*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)); let mut __decomp_7: (Elem, Elem) = p.clone(); - let x: *mut Elem = (unsafe { get_8(&mut __decomp_7) }); - let y: *mut Elem = (unsafe { get_9(&mut __decomp_7) }); + let x: *mut Elem = &mut __decomp_7.0; + let y: *mut Elem = &mut __decomp_7.1; assert!( ((*std::cell::LazyCell::force_mut(&mut *&raw mut copies_0)) == ((before_copies) + (2))) ); diff --git a/tests/unit/out/unsafe/structured_binding_pair.rs b/tests/unit/out/unsafe/structured_binding_pair.rs index 88a1a0a40..0bf6e072c 100644 --- a/tests/unit/out/unsafe/structured_binding_pair.rs +++ b/tests/unit/out/unsafe/structured_binding_pair.rs @@ -17,21 +17,21 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut __decomp_1: (i32, bool) = (unsafe { make_std_pair_0(5) }); - let value: *mut i32 = (unsafe { get_2(&mut __decomp_1) }); - let positive: *mut bool = (unsafe { get_3(&mut __decomp_1) }); + let value: *mut i32 = &mut __decomp_1.0; + let positive: *mut bool = &mut __decomp_1.1; assert!(((*value) == (5))); assert!(((*positive) as bool)); let mut p: (i32, i32) = (1.into(), 2.into()); - let mut __decomp_4: (i32, i32) = p.clone(); - let a: *mut i32 = (unsafe { get_5(&mut __decomp_4) }); - let b: *mut i32 = (unsafe { get_6(&mut __decomp_4) }); + let mut __decomp_2: (i32, i32) = p.clone(); + let a: *mut i32 = &mut __decomp_2.0; + let b: *mut i32 = &mut __decomp_2.1; (*a) = 10; assert!(((*a) == (10))); assert!(((*b) == (2))); assert!(((p.0) == (1))); - let __decomp_7: *mut (i32, i32) = &mut p; - let x: *mut i32 = &mut (*__decomp_7).0; - let y: *mut i32 = &mut (*__decomp_7).1; + let __decomp_3: *mut (i32, i32) = &mut p; + let x: *mut i32 = &mut (*__decomp_3).0; + let y: *mut i32 = &mut (*__decomp_3).1; (*x) = 3; (*y) += 4; assert!(((p.0) == (3))); From 3d04fd0219362a91653c8e9b68d2568a2301713c Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Thu, 15 Oct 2026 11:13:18 +0100 Subject: [PATCH 21/21] Translat move ctors for records that have custom move ctors fields --- cpp2rust/converter/converter_lib.cpp | 40 ++++++++++++++----- tests/unit/out/refcount/copy_ctor.rs | 11 ++++- .../structured_binding_element_ctor.rs | 12 +++++- tests/unit/out/unsafe/copy_ctor.rs | 12 +++++- .../unsafe/structured_binding_element_ctor.rs | 13 +++++- 5 files changed, 70 insertions(+), 18 deletions(-) diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index f7bd2335e..ad718cfe6 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -528,12 +528,21 @@ IsConvertibleImplicitMemberParent(const clang::CXXRecordDecl *decl) { decl->getNumBases() == 0; } +static bool HasFieldWithMoveFrom(const clang::RecordDecl *decl) { + return llvm::any_of(decl->fields(), [](const clang::FieldDecl *field) { + auto *record = field->getType()->getAsRecordDecl(); + return record && HasMoveFromConstructor(record); + }); +} + bool IsConvertibleMoveConstructor(const clang::CXXConstructorDecl *ctor) { - return ctor->isMoveConstructor() && !ctor->isDeleted() && - IsConvertibleImplicitMemberParent(ctor->getParent()) && - (ctor->isUserProvided() || - !HasDefaultedCopyConstructor(ctor->getParent())) && - ctor->hasBody(); + auto *parent = ctor->getParent(); + if (!ctor->isMoveConstructor() || ctor->isDeleted() || !ctor->hasBody() || + !IsConvertibleImplicitMemberParent(parent)) { + return false; + } + return ctor->isUserProvided() || !HasDefaultedCopyConstructor(parent) || + HasFieldWithMoveFrom(parent); } bool HasMoveFromConstructor(const clang::RecordDecl *decl) { @@ -544,12 +553,23 @@ bool HasMoveFromConstructor(const clang::RecordDecl *decl) { }); } +static bool HasFieldWithMoveAssign(const clang::RecordDecl *decl) { + return llvm::any_of(decl->fields(), [](const clang::FieldDecl *field) { + auto *record = field->getType()->getAsCXXRecordDecl(); + return record && llvm::any_of(record->methods(), [](auto *method) { + return IsConvertibleMoveAssignment(method); + }); + }); +} + bool IsConvertibleMoveAssignment(const clang::CXXMethodDecl *method) { - return method->isMoveAssignmentOperator() && !method->isDeleted() && - IsConvertibleImplicitMemberParent(method->getParent()) && - (method->isUserProvided() || - !HasDefaultedCopyAssignment(method->getParent())) && - method->hasBody(); + auto *parent = method->getParent(); + if (!method->isMoveAssignmentOperator() || method->isDeleted() || + !method->hasBody() || !IsConvertibleImplicitMemberParent(parent)) { + return false; + } + return method->isUserProvided() || !HasDefaultedCopyAssignment(parent) || + HasFieldWithMoveAssign(parent); } bool IsConvertibleImplicitMember(const clang::CXXMethodDecl *method) { diff --git a/tests/unit/out/refcount/copy_ctor.rs b/tests/unit/out/refcount/copy_ctor.rs index 5fe0d932a..070c80b57 100644 --- a/tests/unit/out/refcount/copy_ctor.rs +++ b/tests/unit/out/refcount/copy_ctor.rs @@ -143,13 +143,20 @@ impl Clone for Box_int_ { Box_int_::copy_from(__src.as_pointer()) } } -#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)] #[byte_size(4)] pub struct Owner { #[offset(0)] #[byte_size(4)] pub box_: Box_int_, } +impl Owner { + pub fn move_from(_a0: Ptr) -> Self { + Self { + box_: Box_int_::move_from({ field_ptr!(_a0, box_) }), + } + } +} #[derive(Record, ByteRepr, VaArg, FnPtrArg, Default)] #[byte_size(4)] pub struct OutOfLine { @@ -272,7 +279,7 @@ fn main_0() -> i32 { let o: Value = Rc::new(RefCell::new(Owner { box_: Box_int_::new({ 3 }), })); - let mut o2: Owner = (*o.borrow()).clone(); + let mut o2: Owner = Owner::move_from({ o.as_pointer() }); assert!((o2.box_.val == 3)); let ol1: Value = Rc::new(RefCell::new(OutOfLine::new({ 5 }))); let mut ol2: OutOfLine = OutOfLine::copy_from({ ol1.as_pointer() }); diff --git a/tests/unit/out/refcount/structured_binding_element_ctor.rs b/tests/unit/out/refcount/structured_binding_element_ctor.rs index 63f73f3e6..85fef2b42 100644 --- a/tests/unit/out/refcount/structured_binding_element_ctor.rs +++ b/tests/unit/out/refcount/structured_binding_element_ctor.rs @@ -44,7 +44,7 @@ impl Clone for Elem { Elem::copy_from(__src.as_pointer()) } } -#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, Default)] +#[derive(Clone, Record, ByteRepr, VaArg, FnPtrArg, MoveCtor, Default)] #[byte_size(8)] pub struct Two { #[offset(0)] @@ -54,6 +54,14 @@ pub struct Two { #[byte_size(4)] pub b: Elem, } +impl Two { + pub fn move_from(_a0: Ptr) -> Self { + Self { + a: Elem::move_from({ field_ptr!(_a0, a) }), + b: Elem::move_from({ field_ptr!(_a0, b) }), + } + } +} pub fn make_two_2() -> Two { return Two { a: Elem::new({ 1 }), @@ -81,7 +89,7 @@ fn main_0() -> i32 { assert!(({ (*__decomp_4.upgrade().deref()).a.v } == 1)); field!(field!(__decomp_4, a), v).write(50); assert!(({ (*t.borrow()).a.v } == 50)); - let __decomp_5: Value = Rc::new(RefCell::new((*t.borrow()).clone())); + let __decomp_5: Value = Rc::new(RefCell::new(Two::move_from({ t.as_pointer() }))); assert!((moves_1.with(|rc| *rc.borrow()) == (base_moves + 2))); assert!(({ (*__decomp_5.borrow()).a.v } == 1050)); assert!(({ (*__decomp_5.borrow()).b.v } == 1002)); diff --git a/tests/unit/out/unsafe/copy_ctor.rs b/tests/unit/out/unsafe/copy_ctor.rs index f6aaee237..d25d2dd8f 100644 --- a/tests/unit/out/unsafe/copy_ctor.rs +++ b/tests/unit/out/unsafe/copy_ctor.rs @@ -113,10 +113,18 @@ impl Clone for Box_int_ { } } #[repr(C)] -#[derive(Clone, VaArg, FnPtrArg, Default)] +#[derive(Clone, VaArg, FnPtrArg, MoveCtorUnsafe, Default)] pub struct Owner { pub box_: Box_int_, } +impl Owner { + pub unsafe fn move_from(_a0: *mut Owner) -> Self { + let mut this = Self { + box_: Box_int_::move_from({ &mut (*_a0).box_ }), + }; + this + } +} #[repr(C)] #[derive(VaArg, FnPtrArg, Default)] pub struct OutOfLine { @@ -226,7 +234,7 @@ unsafe fn main_0() -> i32 { let mut o: Owner = Owner { box_: Box_int_::new({ 3 }), }; - let mut o2: Owner = o.clone(); + let mut o2: Owner = Owner::move_from({ &mut o }); assert!(((o2.box_.val) == (3))); let mut ol1: OutOfLine = OutOfLine::new({ 5 }); let mut ol2: OutOfLine = OutOfLine::copy_from({ &ol1 }); diff --git a/tests/unit/out/unsafe/structured_binding_element_ctor.rs b/tests/unit/out/unsafe/structured_binding_element_ctor.rs index dd1efe3bb..db6370f5b 100644 --- a/tests/unit/out/unsafe/structured_binding_element_ctor.rs +++ b/tests/unit/out/unsafe/structured_binding_element_ctor.rs @@ -40,11 +40,20 @@ impl Clone for Elem { } } #[repr(C)] -#[derive(Clone, VaArg, FnPtrArg, Default)] +#[derive(Clone, VaArg, FnPtrArg, MoveCtorUnsafe, Default)] pub struct Two { pub a: Elem, pub b: Elem, } +impl Two { + pub unsafe fn move_from(_a0: *mut Two) -> Self { + let mut this = Self { + a: Elem::move_from({ &mut (*_a0).a }), + b: Elem::move_from({ &mut (*_a0).b }), + }; + this + } +} pub unsafe fn make_two_2() -> Two { return Two { a: Elem::new({ 1 }), @@ -74,7 +83,7 @@ unsafe fn main_0() -> i32 { assert!((((*__decomp_4).a.v) == (1))); (*__decomp_4).a.v = 50; assert!(((t.a.v) == (50))); - let mut __decomp_5: Two = t.clone(); + let mut __decomp_5: Two = Two::move_from({ &mut t }); assert!(((*std::cell::LazyCell::force_mut(&mut *&raw mut moves_1)) == ((base_moves) + (2)))); assert!(((__decomp_5.a.v) == (1050))); assert!(((__decomp_5.b.v) == (1002)));