From cfb6ea846862c07f3e63a70d6ff586c81f421b53 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 19 Oct 2026 13:25:09 +0100 Subject: [PATCH 1/9] Move std::array default in rules --- cpp2rust/converter/converter.cpp | 27 ------------------- rules/array/tgt_unsafe.rs | 4 +-- tests/unit/out/refcount/empty_array_init.rs | 4 +-- .../out/refcount/inline_container_fields.rs | 2 +- .../refcount/libc_struct_without_default.rs | 2 +- .../out/unsafe/inline_container_fields.rs | 2 +- .../out/unsafe/libc_struct_without_default.rs | 2 +- 7 files changed, 7 insertions(+), 36 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index dae3b5916..9c3b2eb4e 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -4302,33 +4302,6 @@ std::string Converter::GetArrayDefaultAsString(clang::QualType qual_type) { if (clang::isa(qual_type)) { return "[]"; } - if (IsStdDecl(qual_type->getAsCXXRecordDecl(), "array")) { - assert(GetTemplateArgs(qual_type).has_value()); - auto template_args = *GetTemplateArgs(qual_type); - assert(template_args.size() == 2); - auto array_size = template_args[1]; - unsigned size = 0; - switch (array_size.getKind()) { - case clang::TemplateArgument::Expression: { - auto array_size_expr = array_size.getAsExpr(); - assert(array_size_expr && !array_size_expr->isValueDependent()); - clang::Expr::EvalResult result; - ENSURE(array_size_expr->EvaluateAsInt(result, ctx_)); - size = result.Val.getInt().getZExtValue(); - break; - } - case clang::TemplateArgument::Integral: { - size = array_size.getAsIntegral().getZExtValue(); - break; - } - default: - assert(0 && "Unsupported array size kind"); - break; - } - return std::format( - "std::array::from_fn::<_, {}, _>(|_| Default::default()).to_vec()", - size); - } return {}; } diff --git a/rules/array/tgt_unsafe.rs b/rules/array/tgt_unsafe.rs index 63de9ffd5..7a26a7fd5 100644 --- a/rules/array/tgt_unsafe.rs +++ b/rules/array/tgt_unsafe.rs @@ -3,8 +3,8 @@ use libcc2rs::*; -fn t1() -> Vec { - Default::default() +fn t1() -> Vec { + std::array::from_fn::<_, T2, _>(|_| ::default()).to_vec() } fn t2() -> usize { diff --git a/tests/unit/out/refcount/empty_array_init.rs b/tests/unit/out/refcount/empty_array_init.rs index 047804591..279089ea4 100644 --- a/tests/unit/out/refcount/empty_array_init.rs +++ b/tests/unit/out/refcount/empty_array_init.rs @@ -11,9 +11,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let vec_: Value> = Rc::new(RefCell::new( - std::array::from_fn::<_, 3, _>(|_| Default::default()).to_vec(), - )); + let vec_: Value> = Rc::new(RefCell::new()); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/inline_container_fields.rs b/tests/unit/out/refcount/inline_container_fields.rs index bacfe82e3..eab5d8f62 100644 --- a/tests/unit/out/refcount/inline_container_fields.rs +++ b/tests/unit/out/refcount/inline_container_fields.rs @@ -55,7 +55,7 @@ impl Default for State { grid: (0..2) .map(|_| (0..3).map(|_| 0_i32).collect::>()) .collect::]>>(), - arr: std::array::from_fn::<_, 3, _>(|_| Default::default()).to_vec(), + arr: std::array::from_fn::<_, 3_u64, _>(|_| ::default()).to_vec(), elems: Default::default(), rows: Default::default(), } diff --git a/tests/unit/out/refcount/libc_struct_without_default.rs b/tests/unit/out/refcount/libc_struct_without_default.rs index 03534f0ad..60df8d301 100644 --- a/tests/unit/out/refcount/libc_struct_without_default.rs +++ b/tests/unit/out/refcount/libc_struct_without_default.rs @@ -20,7 +20,7 @@ impl Default for UserDefined { fn default() -> Self { { UserDefined { - a: std::array::from_fn::<_, 1, _>(|_| Default::default()).to_vec(), + a: std::array::from_fn::<_, 1_u64, _>(|_| ::default()).to_vec(), v: Default::default(), } } diff --git a/tests/unit/out/unsafe/inline_container_fields.rs b/tests/unit/out/unsafe/inline_container_fields.rs index 3a8fb0c3a..1032bf541 100644 --- a/tests/unit/out/unsafe/inline_container_fields.rs +++ b/tests/unit/out/unsafe/inline_container_fields.rs @@ -28,7 +28,7 @@ impl Default for State { State { count: 0_i32, grid: [[0_i32; 3]; 2], - arr: std::array::from_fn::<_, 3, _>(|_| Default::default()).to_vec(), + arr: std::array::from_fn::<_, 3_u64, _>(|_| ::default()).to_vec(), elems: Default::default(), rows: Default::default(), } diff --git a/tests/unit/out/unsafe/libc_struct_without_default.rs b/tests/unit/out/unsafe/libc_struct_without_default.rs index 907ab0a9c..919234249 100644 --- a/tests/unit/out/unsafe/libc_struct_without_default.rs +++ b/tests/unit/out/unsafe/libc_struct_without_default.rs @@ -16,7 +16,7 @@ impl Default for UserDefined { fn default() -> Self { unsafe { UserDefined { - a: std::array::from_fn::<_, 1, _>(|_| Default::default()).to_vec(), + a: std::array::from_fn::<_, 1_u64, _>(|_| ::default()).to_vec(), v: Default::default(), } } From 3ee8ea5346ded18650497b529a36a84c34f36f22 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 19 Oct 2026 13:28:32 +0100 Subject: [PATCH 2/9] FIx default for std::array --- cpp2rust/converter/converter.cpp | 8 +------- cpp2rust/converter/models/converter_refcount.cpp | 2 +- tests/unit/out/refcount/empty_array_init.rs | 4 +++- tests/unit/out/unsafe/empty_array_init.rs | 2 +- 4 files changed, 6 insertions(+), 10 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 9c3b2eb4e..2c90f38cb 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -739,12 +739,6 @@ bool Converter::TypeDerivesDefault(clang::QualType qual_type) { return false; } - // Types that need a custom array initializer (e.g., std::array, which is - // translated to Vec) - if (!GetArrayDefaultAsString(qual_type).empty()) { - return false; - } - // libc types do not implement Default if (auto record = qual_type->getAsRecordDecl()) { if (ctx_.getSourceManager().isInSystemHeader(record->getLocation()) && @@ -3637,7 +3631,7 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) { StrCat("vec!"); VisitInitListExpr(init); } else { - StrCat(GetArrayDefaultAsString(qual_type)); + StrCat(GetDefaultAsString(qual_type)); } SetFreshType(qual_type); return false; diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index d2854addd..e658a01bd 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1888,7 +1888,7 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { PushConversionKind push(*this, ConversionKind::Unboxed); ConverterRefCount::VisitInitListExpr(init); } else { - StrCat(GetArrayDefaultAsString(qual_type)); + StrCat(GetDefaultAsString(qual_type)); } computed_expr_type_ = ComputedExprType::FreshValue; return false; diff --git a/tests/unit/out/refcount/empty_array_init.rs b/tests/unit/out/refcount/empty_array_init.rs index 279089ea4..c2ff7fab4 100644 --- a/tests/unit/out/refcount/empty_array_init.rs +++ b/tests/unit/out/refcount/empty_array_init.rs @@ -11,7 +11,9 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let vec_: Value> = Rc::new(RefCell::new()); + let vec_: Value> = Rc::new(RefCell::new(Rc::new(RefCell::new( + std::array::from_fn::<_, 3_u64, _>(|_| ::default()).to_vec(), + )))); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/empty_array_init.rs b/tests/unit/out/unsafe/empty_array_init.rs index 96aec284c..f9e095ce2 100644 --- a/tests/unit/out/unsafe/empty_array_init.rs +++ b/tests/unit/out/unsafe/empty_array_init.rs @@ -13,7 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut vec_: Vec = std::array::from_fn::<_, 3, _>(|_| Default::default()).to_vec(); + let mut vec_: Vec = std::array::from_fn::<_, 3_u64, _>(|_| ::default()).to_vec(); return 0; } pub unsafe fn __cpp2rust_init_globals() {} From dac3147ba8dfd8d14e53e4d8f85470d039d51a87 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 19 Oct 2026 13:34:20 +0100 Subject: [PATCH 3/9] Fix desugared deduced nttp --- cpp2rust/converter/models/converter_refcount.cpp | 1 + cpp2rust/converter/rules/decls.cpp | 9 +++++++++ tests/unit/out/refcount/empty_array_init.rs | 6 +++--- tests/unit/out/refcount/inline_container_fields.rs | 2 +- tests/unit/out/refcount/libc_struct_without_default.rs | 2 +- tests/unit/out/unsafe/empty_array_init.rs | 2 +- tests/unit/out/unsafe/inline_container_fields.rs | 2 +- tests/unit/out/unsafe/libc_struct_without_default.rs | 2 +- 8 files changed, 18 insertions(+), 8 deletions(-) diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index e658a01bd..4618e24e4 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1888,6 +1888,7 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { PushConversionKind push(*this, ConversionKind::Unboxed); ConverterRefCount::VisitInitListExpr(init); } else { + PushConversionKind push(*this, ConversionKind::Unboxed); StrCat(GetDefaultAsString(qual_type)); } computed_expr_type_ = ComputedExprType::FreshValue; diff --git a/cpp2rust/converter/rules/decls.cpp b/cpp2rust/converter/rules/decls.cpp index 90dac3789..5c7eb83a5 100644 --- a/cpp2rust/converter/rules/decls.cpp +++ b/cpp2rust/converter/rules/decls.cpp @@ -91,6 +91,15 @@ DeduceFromType(clang::Sema &sema, clang::TemplateParameterList *params, trial.failed()) { return std::nullopt; } + for (unsigned i = 0; i < deduced.size(); ++i) { + auto nttp = + llvm::dyn_cast(params->getParam(i)); + if (nttp && !nttp->getType()->isDependentType() && + deduced[i].getKind() == clang::TemplateArgument::Integral) { + deduced[i] = clang::TemplateArgument( + sema.Context, deduced[i].getAsIntegral(), nttp->getType()); + } + } return std::vector(deduced.begin(), deduced.end()); } diff --git a/tests/unit/out/refcount/empty_array_init.rs b/tests/unit/out/refcount/empty_array_init.rs index c2ff7fab4..b162babcf 100644 --- a/tests/unit/out/refcount/empty_array_init.rs +++ b/tests/unit/out/refcount/empty_array_init.rs @@ -11,9 +11,9 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let vec_: Value> = Rc::new(RefCell::new(Rc::new(RefCell::new( - std::array::from_fn::<_, 3_u64, _>(|_| ::default()).to_vec(), - )))); + let vec_: Value> = Rc::new(RefCell::new( + std::array::from_fn::<_, 3_usize, _>(|_| ::default()).to_vec(), + )); return 0; } pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/inline_container_fields.rs b/tests/unit/out/refcount/inline_container_fields.rs index eab5d8f62..f5d90c688 100644 --- a/tests/unit/out/refcount/inline_container_fields.rs +++ b/tests/unit/out/refcount/inline_container_fields.rs @@ -55,7 +55,7 @@ impl Default for State { grid: (0..2) .map(|_| (0..3).map(|_| 0_i32).collect::>()) .collect::]>>(), - arr: std::array::from_fn::<_, 3_u64, _>(|_| ::default()).to_vec(), + arr: std::array::from_fn::<_, 3_usize, _>(|_| ::default()).to_vec(), elems: Default::default(), rows: Default::default(), } diff --git a/tests/unit/out/refcount/libc_struct_without_default.rs b/tests/unit/out/refcount/libc_struct_without_default.rs index 60df8d301..c80e7d6f5 100644 --- a/tests/unit/out/refcount/libc_struct_without_default.rs +++ b/tests/unit/out/refcount/libc_struct_without_default.rs @@ -20,7 +20,7 @@ impl Default for UserDefined { fn default() -> Self { { UserDefined { - a: std::array::from_fn::<_, 1_u64, _>(|_| ::default()).to_vec(), + a: std::array::from_fn::<_, 1_usize, _>(|_| ::default()).to_vec(), v: Default::default(), } } diff --git a/tests/unit/out/unsafe/empty_array_init.rs b/tests/unit/out/unsafe/empty_array_init.rs index f9e095ce2..3f484a149 100644 --- a/tests/unit/out/unsafe/empty_array_init.rs +++ b/tests/unit/out/unsafe/empty_array_init.rs @@ -13,7 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut vec_: Vec = std::array::from_fn::<_, 3_u64, _>(|_| ::default()).to_vec(); + let mut vec_: Vec = std::array::from_fn::<_, 3_usize, _>(|_| ::default()).to_vec(); return 0; } pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/inline_container_fields.rs b/tests/unit/out/unsafe/inline_container_fields.rs index 1032bf541..80aedbada 100644 --- a/tests/unit/out/unsafe/inline_container_fields.rs +++ b/tests/unit/out/unsafe/inline_container_fields.rs @@ -28,7 +28,7 @@ impl Default for State { State { count: 0_i32, grid: [[0_i32; 3]; 2], - arr: std::array::from_fn::<_, 3_u64, _>(|_| ::default()).to_vec(), + arr: std::array::from_fn::<_, 3_usize, _>(|_| ::default()).to_vec(), elems: Default::default(), rows: Default::default(), } diff --git a/tests/unit/out/unsafe/libc_struct_without_default.rs b/tests/unit/out/unsafe/libc_struct_without_default.rs index 919234249..d578f3cad 100644 --- a/tests/unit/out/unsafe/libc_struct_without_default.rs +++ b/tests/unit/out/unsafe/libc_struct_without_default.rs @@ -16,7 +16,7 @@ impl Default for UserDefined { fn default() -> Self { unsafe { UserDefined { - a: std::array::from_fn::<_, 1_u64, _>(|_| ::default()).to_vec(), + a: std::array::from_fn::<_, 1_usize, _>(|_| ::default()).to_vec(), v: Default::default(), } } From c540520d2164c96fce715d9cfea0876cf709d880 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 19 Oct 2026 13:56:17 +0100 Subject: [PATCH 4/9] Move aggregate initialziation of array in rules --- cpp2rust/converter/converter.cpp | 15 ++++----- .../converter/models/converter_refcount.cpp | 22 ++++++------- cpp2rust/converter/rules/expr_matcher.cpp | 33 +++++++++++++++++-- cpp2rust/converter/rules/rule_keys.cpp | 4 +++ cpp2rust/converter/rules/rules_loader.cpp | 7 ++++ rules/array/src.cpp | 4 +++ rules/array/tgt_unsafe.rs | 4 +++ tests/unit/out/refcount/init_list.rs | 2 +- .../out/refcount/vector_subscript_direct.rs | 2 +- tests/unit/out/unsafe/init_list.rs | 2 +- .../out/unsafe/vector_subscript_direct.rs | 2 +- 11 files changed, 70 insertions(+), 27 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 2c90f38cb..76934aedc 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -3626,19 +3626,16 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) { } } else if (qual_type->isRecordType()) { const auto *record = qual_type->getAsRecordDecl(); - if (record->getQualifiedNameAsString() == "std::array") { - if (auto init = clang::dyn_cast(expr->getInit(0))) { - StrCat("vec!"); - VisitInitListExpr(init); - } else { - StrCat(GetDefaultAsString(qual_type)); - } + if (syntactic->getNumInits() == 0) { + StrCat(GetDefaultAsString(qual_type)); SetFreshType(qual_type); return false; } - if (syntactic->getNumInits() == 0) { - StrCat(GetDefaultAsString(qual_type)); + if (auto str = + GetMappedAsString(expr, expr->getInits(), expr->getNumInits()); + !str.empty()) { + StrCat(str); SetFreshType(qual_type); return false; } diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 4618e24e4..33ab39fc9 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1882,12 +1882,8 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { if (qual_type->isRecordType()) { const auto *record = qual_type->getAsRecordDecl(); - if (record->getQualifiedNameAsString() == "std::array") { - if (auto init = clang::dyn_cast(expr->getInit(0))) { - StrCat("vec!"); - PushConversionKind push(*this, ConversionKind::Unboxed); - ConverterRefCount::VisitInitListExpr(init); - } else { + if (syntactic->getNumInits() == 0) { + { PushConversionKind push(*this, ConversionKind::Unboxed); StrCat(GetDefaultAsString(qual_type)); } @@ -1895,13 +1891,15 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { return false; } - if (syntactic->getNumInits() == 0) { - { - PushConversionKind push(*this, ConversionKind::Unboxed); - StrCat(GetDefaultAsString(qual_type)); + { + PushConversionKind push(*this, ConversionKind::Unboxed); + if (auto str = + GetMappedAsString(expr, expr->getInits(), expr->getNumInits()); + !str.empty()) { + StrCat(str); + computed_expr_type_ = ComputedExprType::FreshValue; + return false; } - computed_expr_type_ = ComputedExprType::FreshValue; - return false; } if (record->isUnion()) { diff --git a/cpp2rust/converter/rules/expr_matcher.cpp b/cpp2rust/converter/rules/expr_matcher.cpp index 2eb8c9b19..235a2df6e 100644 --- a/cpp2rust/converter/rules/expr_matcher.cpp +++ b/cpp2rust/converter/rules/expr_matcher.cpp @@ -22,6 +22,7 @@ #include #include "converter/rules/decls.h" +#include "converter/rules/rule_keys.h" namespace cpp2rust::AstMatcher { @@ -60,8 +61,15 @@ struct RewrittenOperatorUsage { bool operator==(const RewrittenOperatorUsage &) const = default; }; -using ResolvedDecl = std::variant; +struct AggregateUsage { + RuleKeys::TypeKey type; + + bool operator==(const AggregateUsage &) const = default; +}; + +using ResolvedDecl = + std::variant; ResolvedDecl getResolvedDecl(clang::ASTContext &ctx, const clang::Expr *expr, bool must_resolve) { @@ -85,6 +93,14 @@ ResolvedDecl getResolvedDecl(clang::ASTContext &ctx, const clang::Expr *expr, if (auto cast = llvm::dyn_cast(expr)) { return getResolvedDecl(ctx, cast->getSubExpr(), must_resolve); } + if (auto list = llvm::dyn_cast(expr); + list && list->getType()->isRecordType()) { + return AggregateUsage{*RuleKeys::GetTypeKey(list->getType())}; + } + if (auto construct = llvm::dyn_cast(expr); + construct && construct->isListInitialization()) { + return AggregateUsage{*RuleKeys::GetTypeKey(construct->getTypeAsWritten())}; + } if (auto call = llvm::dyn_cast(expr)) { if (auto callee = call->getDirectCallee()) { return callee->getCanonicalDecl(); @@ -149,6 +165,8 @@ std::vector getOperands(clang::ASTContext &ctx, operands.insert(operands.end(), call->arg_begin(), call->arg_end()); } else if (auto construct = llvm::dyn_cast(expr)) { operands.assign(construct->arg_begin(), construct->arg_end()); + } else if (auto list = llvm::dyn_cast(expr)) { + operands.assign(list->inits().begin(), list->inits().end()); } else if (auto member = llvm::dyn_cast(expr)) { auto macro_base = RuleDecls::GetMacroMemberBase(ctx.getSourceManager(), member); @@ -320,6 +338,17 @@ MatchResult matchTemplate(clang::Sema &sema, const clang::Expr *use, auto explicit_args = getResultArgs(sema, rule, use); auto specialization = deduce(sema, rule, explicit_args, getOperands(ctx, use)); + if (!specialization) { + return std::nullopt; + } + if (std::holds_alternative(usage_decl)) { + auto returned = RuleDecls::GetReturned(rule->getTemplatedDecl()); + if (getResolvedDecl(ctx, returned, /*must_resolve=*/false) != usage_decl) { + return std::nullopt; + } + checkCallable(sema, use, rule->getTemplatedDecl()); + return specialization->getTemplateSpecializationArgs()->asArray(); + } auto returned = substituteSpecializationInRuleTmpl(sema, rule, specialization); if (!returned || diff --git a/cpp2rust/converter/rules/rule_keys.cpp b/cpp2rust/converter/rules/rule_keys.cpp index 98e263396..5b83787a6 100644 --- a/cpp2rust/converter/rules/rule_keys.cpp +++ b/cpp2rust/converter/rules/rule_keys.cpp @@ -183,6 +183,10 @@ std::optional getExprKey(clang::ASTContext &ctx, if (llvm::isa(expr)) { return getOperatorKey(ctx, clang::OO_Subscript); } + if (auto list = llvm::dyn_cast(expr); + list && list->getType()->isRecordType()) { + return getConstructorKey(getParent(list->getType())); + } return std::nullopt; } diff --git a/cpp2rust/converter/rules/rules_loader.cpp b/cpp2rust/converter/rules/rules_loader.cpp index 5d9778353..124376bac 100644 --- a/cpp2rust/converter/rules/rules_loader.cpp +++ b/cpp2rust/converter/rules/rules_loader.cpp @@ -489,6 +489,13 @@ std::string ExprKey(clang::ASTContext &ctx, const clang::Expr *expr) { if (auto construct = llvm::dyn_cast(expr)) { return FunctionKey(construct->getConstructor()); } + if (auto list = llvm::dyn_cast(expr)) { + if (auto record = list->getType()->getAsRecordDecl(); + record && !IsUserDefinedDecl(record)) { + return ConstructorKey(ClassKey(record)); + } + return {}; + } if (auto member = llvm::dyn_cast(expr)) { if (RuleDecls::GetMacroMemberBase(ctx.getSourceManager(), member)) { return clang::Lexer::getImmediateMacroName(member->getMemberLoc(), diff --git a/rules/array/src.cpp b/rules/array/src.cpp index ff2f6b4cd..2736d24b6 100644 --- a/rules/array/src.cpp +++ b/rules/array/src.cpp @@ -41,3 +41,7 @@ template std::array &f7(std::array &dst, const std::array &src) { return dst = src; } + +template std::array f8(T1 (&&a0)[T2]) { + return std::array{a0}; +} diff --git a/rules/array/tgt_unsafe.rs b/rules/array/tgt_unsafe.rs index 7a26a7fd5..a385a0ee4 100644 --- a/rules/array/tgt_unsafe.rs +++ b/rules/array/tgt_unsafe.rs @@ -38,3 +38,7 @@ unsafe fn f6(a0: Vec) -> Vec { unsafe fn f7(a0: &mut Vec, a1: Vec) { *a0 = a1.clone() } + +unsafe fn f8(a0: [T1; T2]) -> Vec { + Vec::from(a0) +} diff --git a/tests/unit/out/refcount/init_list.rs b/tests/unit/out/refcount/init_list.rs index 153950fbc..adbe03e81 100644 --- a/tests/unit/out/refcount/init_list.rs +++ b/tests/unit/out/refcount/init_list.rs @@ -45,7 +45,7 @@ fn main_0() -> i32 { let mut i2: i32 = 0_i32; let mut carr1: [i32; 2] = [1, 2]; let mut carr2: [i32; 3] = [1, 0_i32, 0_i32]; - let arr: Value> = Rc::new(RefCell::new(vec![1, 2, 3])); + let arr: Value> = Rc::new(RefCell::new(Vec::from([1, 2, 3]))); let mut vec_: Vec = vec![1, 2, 3]; ({ f_0(vec![1, 2, 3, 4]) }); let p: Value = Rc::new(RefCell::new(Pair { a: 1, b: 2 })); diff --git a/tests/unit/out/refcount/vector_subscript_direct.rs b/tests/unit/out/refcount/vector_subscript_direct.rs index fcf5afbd4..cbd275e22 100644 --- a/tests/unit/out/refcount/vector_subscript_direct.rs +++ b/tests/unit/out/refcount/vector_subscript_direct.rs @@ -181,7 +181,7 @@ fn main_0() -> i32 { .read()) == 8) ); - let a: Value> = Rc::new(RefCell::new(vec![4, 5, 6])); + let a: Value> = Rc::new(RefCell::new(Vec::from([4, 5, 6]))); let __rhs = ({ (*a.borrow())[0_usize] } + { (*a.borrow())[2_usize] }); (*a.borrow_mut())[1_usize] = __rhs; assert!(({ (*a.borrow())[1_usize] } == 10)); diff --git a/tests/unit/out/unsafe/init_list.rs b/tests/unit/out/unsafe/init_list.rs index f5cd6a11e..97eb56426 100644 --- a/tests/unit/out/unsafe/init_list.rs +++ b/tests/unit/out/unsafe/init_list.rs @@ -47,7 +47,7 @@ unsafe fn main_0() -> i32 { let mut i2: i32 = 0_i32; let mut carr1: [i32; 2] = [1, 2]; let mut carr2: [i32; 3] = [1, 0_i32, 0_i32]; - let mut arr: Vec = vec![1, 2, 3]; + let mut arr: Vec = Vec::from([1, 2, 3]); let mut vec_: Vec = vec![1, 2, 3]; (unsafe { f_0(vec![1, 2, 3, 4]) }); let mut p: Pair = Pair { a: 1, b: 2 }; diff --git a/tests/unit/out/unsafe/vector_subscript_direct.rs b/tests/unit/out/unsafe/vector_subscript_direct.rs index e97789722..e85116962 100644 --- a/tests/unit/out/unsafe/vector_subscript_direct.rs +++ b/tests/unit/out/unsafe/vector_subscript_direct.rs @@ -113,7 +113,7 @@ unsafe fn main_0() -> i32 { grid[(0_usize)][(1_usize)] = grid[(1_usize)][(2_usize)]; grid[(1_usize)][(0_usize)] += grid[(0_usize)][(1_usize)]; assert!(((grid[(0_usize)][(1_usize)]) == (8)) && ((grid[(1_usize)][(0_usize)]) == (8))); - let mut a: Vec = vec![4, 5, 6]; + let mut a: Vec = Vec::from([4, 5, 6]); a[(1_usize)] = ((a[(0_usize)]) + (a[(2_usize)])); assert!(((a[(1_usize)]) == (10))); return 0; From 7b0bef408ac623505a9338dfe392f36bc855cca1 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 19 Oct 2026 14:20:29 +0100 Subject: [PATCH 5/9] Check against array and basic_string --- cpp2rust/converter/converter.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 76934aedc..edcb0c74d 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -739,6 +739,11 @@ bool Converter::TypeDerivesDefault(clang::QualType qual_type) { return false; } + auto *cxx_record = qual_type->getAsCXXRecordDecl(); + if (IsStdDecl(cxx_record, "array") || IsStdDecl(cxx_record, "basic_string")) { + return false; + } + // libc types do not implement Default if (auto record = qual_type->getAsRecordDecl()) { if (ctx_.getSourceManager().isInSystemHeader(record->getLocation()) && From 4e8be460c31950d1ca15a48457c166ec60e67dfd Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 19 Oct 2026 14:34:56 +0100 Subject: [PATCH 6/9] Move std::initializer_list in rules --- cpp2rust/converter/converter.cpp | 10 +++++----- cpp2rust/converter/rules/expr_matcher.cpp | 5 +++++ cpp2rust/converter/rules/rule_keys.cpp | 3 +++ cpp2rust/converter/rules/rules_loader.cpp | 4 ++-- rules/initializer_list/src.cpp | 6 ++++++ rules/initializer_list/tgt_unsafe.rs | 4 ++++ 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index edcb0c74d..57ae5cc49 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -4273,11 +4273,11 @@ bool Converter::VisitClassTemplateDecl(clang::ClassTemplateDecl *decl) { bool Converter::VisitCXXStdInitializerListExpr( clang::CXXStdInitializerListExpr *expr) { - if (expr->getSubExpr()->getType()->isArrayType()) { - // Arrays become Vec's - StrCat("vec!"); - } - Convert(expr->getSubExpr()); + auto *backing = expr->getSubExpr(); + auto str = GetMappedAsString(expr, &backing, 1); + ENSURE(!str.empty()); + StrCat(str); + SetFreshType(expr->getType()); return false; } diff --git a/cpp2rust/converter/rules/expr_matcher.cpp b/cpp2rust/converter/rules/expr_matcher.cpp index 235a2df6e..34bf3ac6d 100644 --- a/cpp2rust/converter/rules/expr_matcher.cpp +++ b/cpp2rust/converter/rules/expr_matcher.cpp @@ -97,6 +97,9 @@ ResolvedDecl getResolvedDecl(clang::ASTContext &ctx, const clang::Expr *expr, list && list->getType()->isRecordType()) { return AggregateUsage{*RuleKeys::GetTypeKey(list->getType())}; } + if (llvm::isa(expr)) { + return AggregateUsage{*RuleKeys::GetTypeKey(expr->getType())}; + } if (auto construct = llvm::dyn_cast(expr); construct && construct->isListInitialization()) { return AggregateUsage{*RuleKeys::GetTypeKey(construct->getTypeAsWritten())}; @@ -167,6 +170,8 @@ std::vector getOperands(clang::ASTContext &ctx, operands.assign(construct->arg_begin(), construct->arg_end()); } else if (auto list = llvm::dyn_cast(expr)) { operands.assign(list->inits().begin(), list->inits().end()); + } else if (auto list = llvm::dyn_cast(expr)) { + operands.push_back(list->getSubExpr()->IgnoreImplicit()); } else if (auto member = llvm::dyn_cast(expr)) { auto macro_base = RuleDecls::GetMacroMemberBase(ctx.getSourceManager(), member); diff --git a/cpp2rust/converter/rules/rule_keys.cpp b/cpp2rust/converter/rules/rule_keys.cpp index 5b83787a6..adda286d3 100644 --- a/cpp2rust/converter/rules/rule_keys.cpp +++ b/cpp2rust/converter/rules/rule_keys.cpp @@ -187,6 +187,9 @@ std::optional getExprKey(clang::ASTContext &ctx, list && list->getType()->isRecordType()) { return getConstructorKey(getParent(list->getType())); } + if (llvm::isa(expr)) { + return getConstructorKey(getParent(expr->getType())); + } return std::nullopt; } diff --git a/cpp2rust/converter/rules/rules_loader.cpp b/cpp2rust/converter/rules/rules_loader.cpp index 124376bac..d1b69f724 100644 --- a/cpp2rust/converter/rules/rules_loader.cpp +++ b/cpp2rust/converter/rules/rules_loader.cpp @@ -489,8 +489,8 @@ std::string ExprKey(clang::ASTContext &ctx, const clang::Expr *expr) { if (auto construct = llvm::dyn_cast(expr)) { return FunctionKey(construct->getConstructor()); } - if (auto list = llvm::dyn_cast(expr)) { - if (auto record = list->getType()->getAsRecordDecl(); + if (llvm::isa(expr)) { + if (auto record = expr->getType()->getAsRecordDecl(); record && !IsUserDefinedDecl(record)) { return ConstructorKey(ClassKey(record)); } diff --git a/rules/initializer_list/src.cpp b/rules/initializer_list/src.cpp index 332aba9d4..5e523769e 100644 --- a/rules/initializer_list/src.cpp +++ b/rules/initializer_list/src.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2022-present INESC-ID. // Distributed under the MIT license that can be found in the LICENSE file. +#include #include template using t1 = std::initializer_list; @@ -12,3 +13,8 @@ typename std::initializer_list::size_type f1(const std::initializer_list &o) { return o.size(); } + +template +std::initializer_list f2(const T1 (&a0)[T2]) { + return std::initializer_list{a0}; +} diff --git a/rules/initializer_list/tgt_unsafe.rs b/rules/initializer_list/tgt_unsafe.rs index 768783a36..c5e1828d0 100644 --- a/rules/initializer_list/tgt_unsafe.rs +++ b/rules/initializer_list/tgt_unsafe.rs @@ -14,3 +14,7 @@ fn t2() -> usize { unsafe fn f1(a0: Vec) -> usize { a0.len() } + +unsafe fn f2(a0: [T1; T2]) -> Vec { + Vec::from(a0) +} From d74e93cedaddb1b71bc6b7db50eb5b4f40f7b371 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 19 Oct 2026 14:37:46 +0100 Subject: [PATCH 7/9] Update tests --- tests/ub/out/refcount/dangling-prvalue-as-lvalue.rs | 2 +- tests/ub/out/refcount/row_ptr_outlives_vector.rs | 5 ++++- tests/ub/out/unsafe/dangling-prvalue-as-lvalue.rs | 2 +- tests/ub/out/unsafe/row_ptr_outlives_vector.rs | 2 +- tests/unit/out/refcount/char_printing.rs | 2 +- tests/unit/out/refcount/char_printing_cerr.rs | 2 +- tests/unit/out/refcount/comma_operator.rs | 2 +- tests/unit/out/refcount/find.rs | 2 +- tests/unit/out/refcount/init_list.rs | 4 ++-- tests/unit/out/refcount/initializer_list.rs | 6 +++--- tests/unit/out/refcount/inline_container_fields.rs | 2 +- tests/unit/out/refcount/lambda_capture_library_types.rs | 2 +- tests/unit/out/refcount/nested_vector.rs | 2 +- tests/unit/out/refcount/simple_index.rs | 2 +- tests/unit/out/refcount/split_binop_aliased_borrows.rs | 2 +- tests/unit/out/refcount/unboxed_conditional_iterator.rs | 2 +- tests/unit/out/refcount/vector_subscript_direct.rs | 2 +- tests/unit/out/refcount/void_return.rs | 2 +- tests/unit/out/unsafe/char_printing.rs | 2 +- tests/unit/out/unsafe/char_printing_cerr.rs | 2 +- tests/unit/out/unsafe/comma_operator.rs | 2 +- tests/unit/out/unsafe/find.rs | 2 +- tests/unit/out/unsafe/init_list.rs | 4 ++-- tests/unit/out/unsafe/initializer_list.rs | 6 +++--- tests/unit/out/unsafe/inline_container_fields.rs | 2 +- tests/unit/out/unsafe/lambda_capture_library_types.rs | 2 +- tests/unit/out/unsafe/nested_vector.rs | 2 +- tests/unit/out/unsafe/simple_index.rs | 2 +- tests/unit/out/unsafe/split_binop_aliased_borrows.rs | 2 +- tests/unit/out/unsafe/unboxed_conditional_iterator.rs | 2 +- tests/unit/out/unsafe/vector_subscript_direct.rs | 2 +- tests/unit/out/unsafe/void_return.rs | 2 +- 32 files changed, 41 insertions(+), 38 deletions(-) diff --git a/tests/ub/out/refcount/dangling-prvalue-as-lvalue.rs b/tests/ub/out/refcount/dangling-prvalue-as-lvalue.rs index dea049e02..23916749f 100644 --- a/tests/ub/out/refcount/dangling-prvalue-as-lvalue.rs +++ b/tests/ub/out/refcount/dangling-prvalue-as-lvalue.rs @@ -14,7 +14,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v: Value> = Rc::new(RefCell::new(vec![1, 2])); + let v: Value> = Rc::new(RefCell::new(Vec::from([1, 2]))); let b: Ptr = ({ foo_0(RandomAccessIterator::Vec((v.as_pointer() as Ptr)).iter_deref()) }); (*v.borrow_mut()).clear(); diff --git a/tests/ub/out/refcount/row_ptr_outlives_vector.rs b/tests/ub/out/refcount/row_ptr_outlives_vector.rs index f3f7de668..617533b6a 100644 --- a/tests/ub/out/refcount/row_ptr_outlives_vector.rs +++ b/tests/ub/out/refcount/row_ptr_outlives_vector.rs @@ -7,7 +7,10 @@ use std::io::{Read, Seek, Write}; use std::os::fd::AsFd; use std::rc::{Rc, Weak}; pub fn second_row_0() -> Ptr { - let rows: Value>> = Rc::new(RefCell::new(vec![vec![1, 2, 3], vec![4, 5, 6]])); + let rows: Value>> = Rc::new(RefCell::new(Vec::from([ + Vec::from([1, 2, 3]), + Vec::from([4, 5, 6]), + ]))); return ((rows.as_pointer() as Ptr>) .offset(1_usize) .as_pointer() as Ptr); diff --git a/tests/ub/out/unsafe/dangling-prvalue-as-lvalue.rs b/tests/ub/out/unsafe/dangling-prvalue-as-lvalue.rs index 2abcddf6e..bdbe897b1 100644 --- a/tests/ub/out/unsafe/dangling-prvalue-as-lvalue.rs +++ b/tests/ub/out/unsafe/dangling-prvalue-as-lvalue.rs @@ -16,7 +16,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut v: Vec = vec![1, 2]; + let mut v: Vec = Vec::from([1, 2]); let b: *const i32 = (unsafe { foo_0(&(*UnsafeRandomAccessIterator::Vec(v.as_mut_ptr()).iter_deref())) }); v.clear(); diff --git a/tests/ub/out/unsafe/row_ptr_outlives_vector.rs b/tests/ub/out/unsafe/row_ptr_outlives_vector.rs index 51b8fbe4d..00e7f64a8 100644 --- a/tests/ub/out/unsafe/row_ptr_outlives_vector.rs +++ b/tests/ub/out/unsafe/row_ptr_outlives_vector.rs @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn second_row_0() -> *mut i32 { - let mut rows: Vec> = vec![vec![1, 2, 3], vec![4, 5, 6]]; + let mut rows: Vec> = Vec::from([Vec::from([1, 2, 3]), Vec::from([4, 5, 6])]); return rows[(1_usize)].as_mut_ptr(); } pub fn main() { diff --git a/tests/unit/out/refcount/char_printing.rs b/tests/unit/out/refcount/char_printing.rs index 331031af2..34d3eaefe 100644 --- a/tests/unit/out/refcount/char_printing.rs +++ b/tests/unit/out/refcount/char_printing.rs @@ -11,7 +11,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let mut vec_: Vec = vec![195_u8, 167_u8]; + let mut vec_: Vec = Vec::from([195_u8, 167_u8]); let mut i: i32 = 27; let str: Value> = Rc::new(RefCell::new({ let mut __bytes = Ptr::::from_string_literal(b"foo.").to_c_bytes(); diff --git a/tests/unit/out/refcount/char_printing_cerr.rs b/tests/unit/out/refcount/char_printing_cerr.rs index 1ae6912a7..4bcadd46d 100644 --- a/tests/unit/out/refcount/char_printing_cerr.rs +++ b/tests/unit/out/refcount/char_printing_cerr.rs @@ -11,7 +11,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let mut vec_: Vec = vec![195_u8, 167_u8]; + let mut vec_: Vec = Vec::from([195_u8, 167_u8]); let mut i: i32 = 27; let str: Value> = Rc::new(RefCell::new({ let mut __bytes = Ptr::::from_string_literal(b"bar.").to_c_bytes(); diff --git a/tests/unit/out/refcount/comma_operator.rs b/tests/unit/out/refcount/comma_operator.rs index 91f0d8eda..a7cc2c063 100644 --- a/tests/unit/out/refcount/comma_operator.rs +++ b/tests/unit/out/refcount/comma_operator.rs @@ -62,7 +62,7 @@ fn main_0() -> i32 { assert!((a == 1)); assert!((b == 2)); } - let v1: Value> = Rc::new(RefCell::new(vec![1, 2])); + let v1: Value> = Rc::new(RefCell::new(Vec::from([1, 2]))); let mut v2: Vec = { a = 5; (*v1.borrow()).clone() diff --git a/tests/unit/out/refcount/find.rs b/tests/unit/out/refcount/find.rs index de56d1695..bd60dc9bb 100644 --- a/tests/unit/out/refcount/find.rs +++ b/tests/unit/out/refcount/find.rs @@ -100,7 +100,7 @@ fn main_0() -> i32 { __it } == RandomAccessIterator::Vec((v.as_pointer() as Ptr))) ); - let w: Value> = Rc::new(RefCell::new(vec![1, 2, 3, 4, 5])); + let w: Value> = Rc::new(RefCell::new(Vec::from([1, 2, 3, 4, 5]))); assert!( { let mut __it = diff --git a/tests/unit/out/refcount/init_list.rs b/tests/unit/out/refcount/init_list.rs index adbe03e81..05b2b0a5d 100644 --- a/tests/unit/out/refcount/init_list.rs +++ b/tests/unit/out/refcount/init_list.rs @@ -46,8 +46,8 @@ fn main_0() -> i32 { let mut carr1: [i32; 2] = [1, 2]; let mut carr2: [i32; 3] = [1, 0_i32, 0_i32]; let arr: Value> = Rc::new(RefCell::new(Vec::from([1, 2, 3]))); - let mut vec_: Vec = vec![1, 2, 3]; - ({ f_0(vec![1, 2, 3, 4]) }); + let mut vec_: Vec = Vec::from([1, 2, 3]); + ({ f_0(Vec::from([1, 2, 3, 4])) }); let p: Value = Rc::new(RefCell::new(Pair { a: 1, b: 2 })); let h: Value = Rc::new(RefCell::new(::default())); ({ HolderImpl::operator_assign_1(&h.as_pointer(), p.as_pointer()) }); diff --git a/tests/unit/out/refcount/initializer_list.rs b/tests/unit/out/refcount/initializer_list.rs index 30781d52d..329c45eaa 100644 --- a/tests/unit/out/refcount/initializer_list.rs +++ b/tests/unit/out/refcount/initializer_list.rs @@ -18,11 +18,11 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - assert!((({ f_0(vec![1, 2, 3,],) }) == 3_usize)); - let mut v: Vec = vec![4, 5, 6]; + assert!((({ f_0(Vec::from([1, 2, 3,]),) }) == 3_usize)); + let mut v: Vec = Vec::from([4, 5, 6]); assert!((v.len() == 3_usize)); assert!((((v[0_usize] + v[1_usize]) + v[2_usize]) == 15)); - let l: Value> = Rc::new(RefCell::new(vec![7, 8])); + let l: Value> = Rc::new(RefCell::new(Vec::from([7, 8]))); assert!(((*l.borrow()).len() == 2_usize)); return 0; } diff --git a/tests/unit/out/refcount/inline_container_fields.rs b/tests/unit/out/refcount/inline_container_fields.rs index f5d90c688..b94ff34a9 100644 --- a/tests/unit/out/refcount/inline_container_fields.rs +++ b/tests/unit/out/refcount/inline_container_fields.rs @@ -100,7 +100,7 @@ pub fn fill_1(mut s: Ptr) { i.prefix_inc(); } { - let __a1 = vec![1, 2, 3]; + let __a1 = Vec::from([1, 2, 3]); field!(s, rows).with_mut(|__v: &mut Vec>| __v.push(__a1)) }; } diff --git a/tests/unit/out/refcount/lambda_capture_library_types.rs b/tests/unit/out/refcount/lambda_capture_library_types.rs index be1be47d0..25620a691 100644 --- a/tests/unit/out/refcount/lambda_capture_library_types.rs +++ b/tests/unit/out/refcount/lambda_capture_library_types.rs @@ -11,7 +11,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v: Value> = Rc::new(RefCell::new(vec![1, 2])); + let v: Value> = Rc::new(RefCell::new(Vec::from([1, 2]))); let f: Value i32>> = Rc::new(RefCell::new(lambda!( { let v: Value> = Rc::new(RefCell::new((*v.borrow()).clone())); diff --git a/tests/unit/out/refcount/nested_vector.rs b/tests/unit/out/refcount/nested_vector.rs index 2558959f8..5b5a6bb47 100644 --- a/tests/unit/out/refcount/nested_vector.rs +++ b/tests/unit/out/refcount/nested_vector.rs @@ -12,7 +12,7 @@ pub fn main() { } fn main_0() -> i32 { let v1: Value>> = Rc::new(RefCell::new(Vec::new())); - let mut v2: Vec = vec![1]; + let mut v2: Vec = Vec::from([1]); { let a0_clone = v2.clone(); (*v1.borrow_mut()).push(a0_clone) diff --git a/tests/unit/out/refcount/simple_index.rs b/tests/unit/out/refcount/simple_index.rs index d0c49d175..9c6a8a7b4 100644 --- a/tests/unit/out/refcount/simple_index.rs +++ b/tests/unit/out/refcount/simple_index.rs @@ -11,7 +11,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v: Value> = Rc::new(RefCell::new(vec![true])); + let v: Value> = Rc::new(RefCell::new(Vec::from([true]))); assert!(((*v.borrow())[0_usize] as bool)); return 0; } diff --git a/tests/unit/out/refcount/split_binop_aliased_borrows.rs b/tests/unit/out/refcount/split_binop_aliased_borrows.rs index 1691fb8aa..f78f497c7 100644 --- a/tests/unit/out/refcount/split_binop_aliased_borrows.rs +++ b/tests/unit/out/refcount/split_binop_aliased_borrows.rs @@ -11,7 +11,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v: Value> = Rc::new(RefCell::new(vec![1, 2])); + let v: Value> = Rc::new(RefCell::new(Vec::from([1, 2]))); let p: Value> = Rc::new(RefCell::new(RandomAccessIterator::Vec( (v.as_pointer() as Ptr), ))); diff --git a/tests/unit/out/refcount/unboxed_conditional_iterator.rs b/tests/unit/out/refcount/unboxed_conditional_iterator.rs index 21fae41de..e982083f9 100644 --- a/tests/unit/out/refcount/unboxed_conditional_iterator.rs +++ b/tests/unit/out/refcount/unboxed_conditional_iterator.rs @@ -113,7 +113,7 @@ fn main_0() -> i32 { && ((*code.borrow())[(2) as usize] == 1_u32)) && ((*code.borrow())[(3) as usize] == 0_u32) ); - let v: Value> = Rc::new(RefCell::new(vec![1, 2, 3])); + let v: Value> = Rc::new(RefCell::new(Vec::from([1, 2, 3]))); assert!((({ sum_3(v.as_pointer(),) }) == 6)); return 0; } diff --git a/tests/unit/out/refcount/vector_subscript_direct.rs b/tests/unit/out/refcount/vector_subscript_direct.rs index cbd275e22..a4429087c 100644 --- a/tests/unit/out/refcount/vector_subscript_direct.rs +++ b/tests/unit/out/refcount/vector_subscript_direct.rs @@ -45,7 +45,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v: Value> = Rc::new(RefCell::new(vec![1, 2, 3])); + let v: Value> = Rc::new(RefCell::new(Vec::from([1, 2, 3]))); (*v.borrow_mut())[0_usize] = 10; assert!(({ (*v.borrow())[0_usize] } == 10)); (*v.borrow_mut())[1_usize] += 5; diff --git a/tests/unit/out/refcount/void_return.rs b/tests/unit/out/refcount/void_return.rs index a83d7348a..fb8f6cab5 100644 --- a/tests/unit/out/refcount/void_return.rs +++ b/tests/unit/out/refcount/void_return.rs @@ -56,7 +56,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v: Value> = Rc::new(RefCell::new(vec![1, 3, 0, 2, 8, 7])); + let v: Value> = Rc::new(RefCell::new(Vec::from([1, 3, 0, 2, 8, 7]))); ({ let _first: RandomAccessIterator = RandomAccessIterator::Vec((v.as_pointer() as Ptr)); diff --git a/tests/unit/out/unsafe/char_printing.rs b/tests/unit/out/unsafe/char_printing.rs index ad6a98be0..6075099f0 100644 --- a/tests/unit/out/unsafe/char_printing.rs +++ b/tests/unit/out/unsafe/char_printing.rs @@ -13,7 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut vec_: Vec = vec![195_u8, 167_u8]; + let mut vec_: Vec = Vec::from([195_u8, 167_u8]); let mut i: i32 = 27; let mut str: Vec = { let s = c"foo.".as_ptr(); diff --git a/tests/unit/out/unsafe/char_printing_cerr.rs b/tests/unit/out/unsafe/char_printing_cerr.rs index ed30e6d91..2d80bd68e 100644 --- a/tests/unit/out/unsafe/char_printing_cerr.rs +++ b/tests/unit/out/unsafe/char_printing_cerr.rs @@ -13,7 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut vec_: Vec = vec![195_u8, 167_u8]; + let mut vec_: Vec = Vec::from([195_u8, 167_u8]); let mut i: i32 = 27; let mut str: Vec = { let s = c"bar.".as_ptr(); diff --git a/tests/unit/out/unsafe/comma_operator.rs b/tests/unit/out/unsafe/comma_operator.rs index c883b1332..8f97760aa 100644 --- a/tests/unit/out/unsafe/comma_operator.rs +++ b/tests/unit/out/unsafe/comma_operator.rs @@ -62,7 +62,7 @@ unsafe fn main_0() -> i32 { assert!(((a) == (1))); assert!(((b) == (2))); } - let mut v1: Vec = vec![1, 2]; + let mut v1: Vec = Vec::from([1, 2]); let mut v2: Vec = { a = 5; (v1).clone() diff --git a/tests/unit/out/unsafe/find.rs b/tests/unit/out/unsafe/find.rs index ca95dc517..6c9200908 100644 --- a/tests/unit/out/unsafe/find.rs +++ b/tests/unit/out/unsafe/find.rs @@ -58,7 +58,7 @@ unsafe fn main_0() -> i32 { __it } == UnsafeRandomAccessIterator::Vec(v.as_mut_ptr())) ); - let mut w: Vec = vec![1, 2, 3, 4, 5]; + let mut w: Vec = Vec::from([1, 2, 3, 4, 5]); assert!( { let mut __it = UnsafeRandomAccessIterator::Vec(w.as_mut_ptr()).iter_add(2_isize); diff --git a/tests/unit/out/unsafe/init_list.rs b/tests/unit/out/unsafe/init_list.rs index 97eb56426..42f59c23e 100644 --- a/tests/unit/out/unsafe/init_list.rs +++ b/tests/unit/out/unsafe/init_list.rs @@ -48,8 +48,8 @@ unsafe fn main_0() -> i32 { let mut carr1: [i32; 2] = [1, 2]; let mut carr2: [i32; 3] = [1, 0_i32, 0_i32]; let mut arr: Vec = Vec::from([1, 2, 3]); - let mut vec_: Vec = vec![1, 2, 3]; - (unsafe { f_0(vec![1, 2, 3, 4]) }); + let mut vec_: Vec = Vec::from([1, 2, 3]); + (unsafe { f_0(Vec::from([1, 2, 3, 4])) }); let mut p: Pair = Pair { a: 1, b: 2 }; let mut h: Holder = ::default(); (unsafe { Holder::operator_assign_1(&mut h, &mut p) }); diff --git a/tests/unit/out/unsafe/initializer_list.rs b/tests/unit/out/unsafe/initializer_list.rs index 8ecadd940..2820df798 100644 --- a/tests/unit/out/unsafe/initializer_list.rs +++ b/tests/unit/out/unsafe/initializer_list.rs @@ -24,11 +24,11 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - assert!(((unsafe { f_0(vec![1, 2, 3,],) }) == (3_usize))); - let mut v: Vec = vec![4, 5, 6]; + assert!(((unsafe { f_0(Vec::from([1, 2, 3,]),) }) == (3_usize))); + let mut v: Vec = Vec::from([4, 5, 6]); assert!(((v.len()) == (3_usize))); assert!(((((v[(0_usize)]) + (v[(1_usize)])) + (v[(2_usize)])) == (15))); - let mut l: Vec = vec![7, 8]; + let mut l: Vec = Vec::from([7, 8]); assert!(((l.len()) == (2_usize))); return 0; } diff --git a/tests/unit/out/unsafe/inline_container_fields.rs b/tests/unit/out/unsafe/inline_container_fields.rs index 80aedbada..3a57f69b3 100644 --- a/tests/unit/out/unsafe/inline_container_fields.rs +++ b/tests/unit/out/unsafe/inline_container_fields.rs @@ -72,7 +72,7 @@ pub unsafe fn fill_1(mut s: *mut State) { i.prefix_inc(); } { - let __a1 = vec![1, 2, 3]; + let __a1 = Vec::from([1, 2, 3]); (*s).rows.push(__a1) }; } diff --git a/tests/unit/out/unsafe/lambda_capture_library_types.rs b/tests/unit/out/unsafe/lambda_capture_library_types.rs index ebdf8087c..9d629a335 100644 --- a/tests/unit/out/unsafe/lambda_capture_library_types.rs +++ b/tests/unit/out/unsafe/lambda_capture_library_types.rs @@ -13,7 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut v: Vec = vec![1, 2]; + let mut v: Vec = Vec::from([1, 2]); let mut f: FnPtr i32> = lambda_unsafe!( { let v: Vec = v.clone(); diff --git a/tests/unit/out/unsafe/nested_vector.rs b/tests/unit/out/unsafe/nested_vector.rs index eb1173d97..b7cbb0392 100644 --- a/tests/unit/out/unsafe/nested_vector.rs +++ b/tests/unit/out/unsafe/nested_vector.rs @@ -14,7 +14,7 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut v1: Vec> = Vec::new(); - let mut v2: Vec = vec![1]; + let mut v2: Vec = Vec::from([1]); { let a0_clone = v2.clone(); v1.push(a0_clone) diff --git a/tests/unit/out/unsafe/simple_index.rs b/tests/unit/out/unsafe/simple_index.rs index 1de75f20c..58d07cb3f 100644 --- a/tests/unit/out/unsafe/simple_index.rs +++ b/tests/unit/out/unsafe/simple_index.rs @@ -13,7 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut v: Vec = vec![true]; + let mut v: Vec = Vec::from([true]); assert!((v[(0_usize)] as bool)); return 0; } diff --git a/tests/unit/out/unsafe/split_binop_aliased_borrows.rs b/tests/unit/out/unsafe/split_binop_aliased_borrows.rs index 2fbfba5d7..e1c2d1d71 100644 --- a/tests/unit/out/unsafe/split_binop_aliased_borrows.rs +++ b/tests/unit/out/unsafe/split_binop_aliased_borrows.rs @@ -13,7 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut v: Vec = vec![1, 2]; + let mut v: Vec = Vec::from([1, 2]); let mut p: UnsafeRandomAccessIterator = UnsafeRandomAccessIterator::Vec(v.as_mut_ptr()); let r: *const i32 = &v[(1_usize)]; (*p.iter_deref()) = (*r); diff --git a/tests/unit/out/unsafe/unboxed_conditional_iterator.rs b/tests/unit/out/unsafe/unboxed_conditional_iterator.rs index 6cbbacdec..f703431bc 100644 --- a/tests/unit/out/unsafe/unboxed_conditional_iterator.rs +++ b/tests/unit/out/unsafe/unboxed_conditional_iterator.rs @@ -95,7 +95,7 @@ unsafe fn main_0() -> i32 { && ((code[(2) as usize]) == (1_u32))) && ((code[(3) as usize]) == (0_u32)) ); - let mut v: Vec = vec![1, 2, 3]; + let mut v: Vec = Vec::from([1, 2, 3]); assert!(((unsafe { sum_3(&mut v,) }) == (6))); return 0; } diff --git a/tests/unit/out/unsafe/vector_subscript_direct.rs b/tests/unit/out/unsafe/vector_subscript_direct.rs index e85116962..b3096e75f 100644 --- a/tests/unit/out/unsafe/vector_subscript_direct.rs +++ b/tests/unit/out/unsafe/vector_subscript_direct.rs @@ -46,7 +46,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut v: Vec = vec![1, 2, 3]; + let mut v: Vec = Vec::from([1, 2, 3]); v[(0_usize)] = 10; assert!(((v[(0_usize)]) == (10))); v[(1_usize)] += 5; diff --git a/tests/unit/out/unsafe/void_return.rs b/tests/unit/out/unsafe/void_return.rs index f224dcedf..172434220 100644 --- a/tests/unit/out/unsafe/void_return.rs +++ b/tests/unit/out/unsafe/void_return.rs @@ -48,7 +48,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut v: Vec = vec![1, 3, 0, 2, 8, 7]; + let mut v: Vec = Vec::from([1, 3, 0, 2, 8, 7]); (unsafe { let _first: UnsafeRandomAccessIterator = UnsafeRandomAccessIterator::Vec(v.as_mut_ptr()); From 6a9412d14289efe2fd67cd0a532d101f98d5b2d2 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 19 Oct 2026 14:46:56 +0100 Subject: [PATCH 8/9] Fix arrity and deduction for aggregate --- cpp2rust/converter/converter.cpp | 1 + .../converter/models/converter_refcount.cpp | 1 + cpp2rust/converter/rules/expr_matcher.cpp | 10 ++++++--- .../refcount/lambda_capture_library_types.rs | 2 +- tests/unit/out/refcount/operator_traits.rs | 21 ++++++++++++++----- .../unsafe/lambda_capture_library_types.rs | 2 +- tests/unit/out/unsafe/operator_traits.rs | 8 +++---- 7 files changed, 31 insertions(+), 14 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 0061ecd82..852dde179 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -3625,6 +3625,7 @@ bool Converter::VisitInitListExpr(clang::InitListExpr *expr) { SetFreshType(qual_type); return false; } + assert(IsUserDefinedDecl(record) && "aggregate list without a rule"); StrCat(GetUnsafeTypeAsString(qual_type)); PushBrace brace(*this); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index a7675da74..a4e1b8acb 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1901,6 +1901,7 @@ bool ConverterRefCount::VisitInitListExpr(clang::InitListExpr *expr) { return false; } } + assert(IsUserDefinedDecl(record) && "aggregate list without a rule"); if (record->isUnion()) { auto *field = expr->getInitializedFieldInUnion(); diff --git a/cpp2rust/converter/rules/expr_matcher.cpp b/cpp2rust/converter/rules/expr_matcher.cpp index 34bf3ac6d..dd57e5f57 100644 --- a/cpp2rust/converter/rules/expr_matcher.cpp +++ b/cpp2rust/converter/rules/expr_matcher.cpp @@ -170,7 +170,8 @@ std::vector getOperands(clang::ASTContext &ctx, operands.assign(construct->arg_begin(), construct->arg_end()); } else if (auto list = llvm::dyn_cast(expr)) { operands.assign(list->inits().begin(), list->inits().end()); - } else if (auto list = llvm::dyn_cast(expr)) { + } else if (auto list = + llvm::dyn_cast(expr)) { operands.push_back(list->getSubExpr()->IgnoreImplicit()); } else if (auto member = llvm::dyn_cast(expr)) { auto macro_base = @@ -256,7 +257,10 @@ clang::TemplateArgumentListInfo getResultArgs(clang::Sema &sema, clang::TemplateArgumentListInfo explicit_args(loc, loc); llvm::SmallBitVector deducible; sema.MarkDeducedTemplateParameters(rule, deducible); - if (deducible.all()) { + bool aggregate = + llvm::isa( + RuleDecls::SkipImplicit(use)); + if (deducible.all() && !aggregate) { return explicit_args; } auto params = rule->getTemplateParameters(); @@ -270,7 +274,7 @@ clang::TemplateArgumentListInfo getResultArgs(clang::Sema &sema, return explicit_args; } auto last = static_cast(deducible.find_last_unset()); - for (unsigned i = 0; i <= last; ++i) { + for (unsigned i = 0; i < params->size() && i <= last; ++i) { auto param = params->getParam(i); if (param->isParameterPack() || (*deduced)[i].isNull()) { break; diff --git a/tests/unit/out/refcount/lambda_capture_library_types.rs b/tests/unit/out/refcount/lambda_capture_library_types.rs index 0d1a9a4e0..f3b2119f1 100644 --- a/tests/unit/out/refcount/lambda_capture_library_types.rs +++ b/tests/unit/out/refcount/lambda_capture_library_types.rs @@ -11,7 +11,7 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let v: Value> = Rc::new(RefCell::new(vec![1, 2])); + let v: Value> = Rc::new(RefCell::new(Vec::from([1, 2]))); let f: Value i32>> = Rc::new(RefCell::new(lambda!( { let v: Value> = Rc::new(RefCell::new((*v.borrow()).clone())); diff --git a/tests/unit/out/refcount/operator_traits.rs b/tests/unit/out/refcount/operator_traits.rs index 133a20072..9515ba0dc 100644 --- a/tests/unit/out/refcount/operator_traits.rs +++ b/tests/unit/out/refcount/operator_traits.rs @@ -159,7 +159,11 @@ pub fn main() { fn main_0() -> i32 { let mut w: Wrapped_int_ = Wrapped_int_ { v: 2 }; assert!((w.v == 2)); - let lts: Value> = Rc::new(RefCell::new(vec![Lt { v: 3 }, Lt { v: 1 }, Lt { v: 2 }])); + let lts: Value> = Rc::new(RefCell::new(Vec::from([ + Lt { v: 3 }, + Lt { v: 1 }, + Lt { v: 2 }, + ]))); { let __n = RandomAccessIterator::Vec((lts.as_pointer() as Ptr).to_end()) .iter_distance(&RandomAccessIterator::Vec((lts.as_pointer() as Ptr))); @@ -191,7 +195,11 @@ fn main_0() -> i32 { (({ (*lts.borrow())[0_usize].v } == 1) && ({ (*lts.borrow())[1_usize].v } == 2)) && ({ (*lts.borrow())[2_usize].v } == 3) ); - let eqs: Value> = Rc::new(RefCell::new(vec![Eq { v: 1 }, Eq { v: 2 }, Eq { v: 3 }])); + let eqs: Value> = Rc::new(RefCell::new(Vec::from([ + Eq { v: 1 }, + Eq { v: 2 }, + Eq { v: 3 }, + ]))); let mut two: Eq = Eq { v: 2 }; let mut nine: Eq = Eq { v: 9 }; assert!( @@ -219,8 +227,11 @@ fn main_0() -> i32 { __it } == RandomAccessIterator::Vec((eqs.as_pointer() as Ptr).to_end()) ); - let cmps: Value> = - Rc::new(RefCell::new(vec![Cmp { v: 3 }, Cmp { v: 1 }, Cmp { v: 2 }])); + let cmps: Value> = Rc::new(RefCell::new(Vec::from([ + Cmp { v: 3 }, + Cmp { v: 1 }, + Cmp { v: 2 }, + ]))); { let __n = RandomAccessIterator::Vec((cmps.as_pointer() as Ptr).to_end()) .iter_distance(&RandomAccessIterator::Vec((cmps.as_pointer() as Ptr))); @@ -264,7 +275,7 @@ fn main_0() -> i32 { .with(|__s| __s.v) == 3) ); - let frees: Value> = Rc::new(RefCell::new(vec![Free { v: 2 }, Free { v: 1 }])); + let frees: Value> = Rc::new(RefCell::new(Vec::from([Free { v: 2 }, Free { v: 1 }]))); { let __n = RandomAccessIterator::Vec((frees.as_pointer() as Ptr).to_end()) .iter_distance(&RandomAccessIterator::Vec( diff --git a/tests/unit/out/unsafe/lambda_capture_library_types.rs b/tests/unit/out/unsafe/lambda_capture_library_types.rs index ffa85ea9a..169d7c236 100644 --- a/tests/unit/out/unsafe/lambda_capture_library_types.rs +++ b/tests/unit/out/unsafe/lambda_capture_library_types.rs @@ -13,7 +13,7 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut v: Vec = vec![1, 2]; + let mut v: Vec = Vec::from([1, 2]); let mut f: FnPtr i32> = lambda_unsafe!( { let v: Vec = v.clone(); diff --git a/tests/unit/out/unsafe/operator_traits.rs b/tests/unit/out/unsafe/operator_traits.rs index 718531e00..607a33fea 100644 --- a/tests/unit/out/unsafe/operator_traits.rs +++ b/tests/unit/out/unsafe/operator_traits.rs @@ -137,7 +137,7 @@ pub fn main() { unsafe fn main_0() -> i32 { let mut w: Wrapped_int_ = Wrapped_int_ { v: 2 }; assert!(((w.v) == (2))); - let mut lts: Vec = vec![Lt { v: 3 }, Lt { v: 1 }, Lt { v: 2 }]; + let mut lts: Vec = Vec::from([Lt { v: 3 }, Lt { v: 1 }, Lt { v: 2 }]); { let __n = UnsafeRandomAccessIterator::Vec(lts.as_mut_ptr().add(lts.len())) .iter_distance(&UnsafeRandomAccessIterator::Vec(lts.as_mut_ptr())); @@ -162,7 +162,7 @@ unsafe fn main_0() -> i32 { assert!( (((lts[(0_usize)].v) == (1)) && ((lts[(1_usize)].v) == (2))) && ((lts[(2_usize)].v) == (3)) ); - let mut eqs: Vec = vec![Eq { v: 1 }, Eq { v: 2 }, Eq { v: 3 }]; + let mut eqs: Vec = Vec::from([Eq { v: 1 }, Eq { v: 2 }, Eq { v: 3 }]); let mut two: Eq = Eq { v: 2 }; let mut nine: Eq = Eq { v: 9 }; assert!( @@ -189,7 +189,7 @@ unsafe fn main_0() -> i32 { __it } == UnsafeRandomAccessIterator::Vec(eqs.as_mut_ptr().add(eqs.len())) ); - let mut cmps: Vec = vec![Cmp { v: 3 }, Cmp { v: 1 }, Cmp { v: 2 }]; + let mut cmps: Vec = Vec::from([Cmp { v: 3 }, Cmp { v: 1 }, Cmp { v: 2 }]); { let __n = UnsafeRandomAccessIterator::Vec(cmps.as_mut_ptr().add(cmps.len())) .iter_distance(&UnsafeRandomAccessIterator::Vec(cmps.as_mut_ptr())); @@ -226,7 +226,7 @@ unsafe fn main_0() -> i32 { .iter_deref()) .v) == (3)) ); - let mut frees: Vec = vec![Free { v: 2 }, Free { v: 1 }]; + let mut frees: Vec = Vec::from([Free { v: 2 }, Free { v: 1 }]); { let __n = UnsafeRandomAccessIterator::Vec(frees.as_mut_ptr().add(frees.len())) .iter_distance(&UnsafeRandomAccessIterator::Vec(frees.as_mut_ptr())); From 525ac72111baab7f3904564847ef8721968fbde3 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 19 Oct 2026 15:58:47 +0100 Subject: [PATCH 9/9] Use <=> instead of == --- cpp2rust/converter/rules/expr_matcher.cpp | 7 ++++--- cpp2rust/converter/rules/rule_keys.h | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cpp2rust/converter/rules/expr_matcher.cpp b/cpp2rust/converter/rules/expr_matcher.cpp index dd57e5f57..13b980485 100644 --- a/cpp2rust/converter/rules/expr_matcher.cpp +++ b/cpp2rust/converter/rules/expr_matcher.cpp @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -51,20 +52,20 @@ bool hasSameArgTypes(clang::ASTContext &ctx, const clang::Expr *use, struct MacroUsage { std::string name; - bool operator==(const MacroUsage &) const = default; + auto operator<=>(const MacroUsage &) const = default; }; struct RewrittenOperatorUsage { const clang::Decl *decl; clang::BinaryOperatorKind op; - bool operator==(const RewrittenOperatorUsage &) const = default; + auto operator<=>(const RewrittenOperatorUsage &) const = default; }; struct AggregateUsage { RuleKeys::TypeKey type; - bool operator==(const AggregateUsage &) const = default; + auto operator<=>(const AggregateUsage &) const = default; }; using ResolvedDecl = diff --git a/cpp2rust/converter/rules/rule_keys.h b/cpp2rust/converter/rules/rule_keys.h index 6eec76ab3..9aaef1ebf 100644 --- a/cpp2rust/converter/rules/rule_keys.h +++ b/cpp2rust/converter/rules/rule_keys.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -26,7 +27,7 @@ struct Member { struct Constructor { const clang::Decl *parent; - bool operator==(const Constructor &) const = default; + auto operator<=>(const Constructor &) const = default; }; struct Unqualified {