From ef11e4dab26b1f7fbf50017edf282ff6a303bf76 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Sat, 10 Oct 2026 22:05:11 +0100 Subject: [PATCH] Unpeel elidable constructors --- cpp2rust/converter/converter.cpp | 5 +++ .../converter/models/converter_refcount.cpp | 5 +++ tests/unit/elidable_iterator_copy_cxx11.cpp | 14 +++++++ .../refcount/elidable_iterator_copy_cxx11.rs | 39 +++++++++++++++++++ tests/unit/out/refcount/huffman.rs | 31 +++++++-------- tests/unit/out/refcount/unique_ptr.rs | 7 +--- tests/unit/out/refcount/unique_ptr_nested.rs | 7 +--- .../unsafe/elidable_iterator_copy_cxx11.rs | 36 +++++++++++++++++ tests/unit/out/unsafe/huffman.rs | 31 +++++++-------- tests/unit/out/unsafe/unique_ptr.rs | 5 +-- tests/unit/out/unsafe/unique_ptr_nested.rs | 7 +--- 11 files changed, 134 insertions(+), 53 deletions(-) create mode 100644 tests/unit/elidable_iterator_copy_cxx11.cpp create mode 100644 tests/unit/out/refcount/elidable_iterator_copy_cxx11.rs create mode 100644 tests/unit/out/unsafe/elidable_iterator_copy_cxx11.rs diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 05bda04ff..dc59f0d05 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -3804,6 +3804,11 @@ void Converter::ConvertCXXConstructExprArgs(clang::CXXConstructExpr *expr) { bool Converter::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) { PushSuppressIteratorClone push(*this, expr); + if (expr->isElidable()) { + Convert(expr->getArg(0)); + return false; + } + if (auto str = GetMappedAsString(expr, expr->getArgs(), expr->getNumArgs()); !str.empty()) { StrCat(str); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index ca7e40335..a9172bc13 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -2372,6 +2372,11 @@ std::string ConverterRefCount::ConvertStream(clang::Expr *expr) { } bool ConverterRefCount::VisitCXXConstructExpr(clang::CXXConstructExpr *expr) { + if (expr->isElidable()) { + Convert(expr->getArg(0)); + return false; + } + // An array is boxed unless it initializes an unboxed variable. bool boxed_array = expr->getType()->isArrayType() && getConversionKind() != ConversionKind::Unboxed; diff --git a/tests/unit/elidable_iterator_copy_cxx11.cpp b/tests/unit/elidable_iterator_copy_cxx11.cpp new file mode 100644 index 000000000..6b8fad741 --- /dev/null +++ b/tests/unit/elidable_iterator_copy_cxx11.cpp @@ -0,0 +1,14 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++11 +#include +#include +#include + +int main() { + std::vector v; + v.push_back(4); + v.push_back(7); + std::vector::iterator it = std::find(v.begin(), v.end(), 7); + assert(it != v.end()); + assert(*it == 7); + return 0; +} diff --git a/tests/unit/out/refcount/elidable_iterator_copy_cxx11.rs b/tests/unit/out/refcount/elidable_iterator_copy_cxx11.rs new file mode 100644 index 000000000..788d4cc32 --- /dev/null +++ b/tests/unit/out/refcount/elidable_iterator_copy_cxx11.rs @@ -0,0 +1,39 @@ +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 v: Value> = Rc::new(RefCell::new(Vec::new())); + { + let __a1 = 4; + (*v.borrow_mut()).push(__a1) + }; + { + let __a1 = 7; + (*v.borrow_mut()).push(__a1) + }; + let it: Value> = Rc::new(RefCell::new({ + let count = ((v.as_pointer() as Ptr).to_end().get_offset() + - (v.as_pointer() as Ptr).get_offset()) as usize; + (v.as_pointer() as Ptr).offset( + (v.as_pointer() as Ptr) + .clone() + .into_iter() + .take(count) + .position(|value_0| value_0.read() == 7) + .unwrap_or(count) as isize, + ) + })); + assert!((*it.borrow()) != (v.as_pointer() as Ptr).to_end()); + assert!((((*it.borrow()).read()) == 7)); + return 0; +} +pub fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/refcount/huffman.rs b/tests/unit/out/refcount/huffman.rs index 20972091e..b7d015196 100644 --- a/tests/unit/out/refcount/huffman.rs +++ b/tests/unit/out/refcount/huffman.rs @@ -74,23 +74,20 @@ impl MinHeap { } } pub fn AllocMinHeap_1(mut capacity: i32) -> Option> { - let mut minHeap: Option> = Some(Rc::new(RefCell::new({ - let __tmp_0: Value = Rc::new(RefCell::new(MinHeap { - size: 0, - capacity: capacity, - arr: Some(Rc::new(RefCell::new( - (0..(capacity as usize)) - .map(|_| >::default()) - .collect::>(), - ))), - next: 0, - alloc: Some(Rc::new(RefCell::new( - (0..10000_usize) - .map(|_| ::default()) - .collect::>(), - ))), - })); - MinHeap::move_from({ __tmp_0.as_pointer() }) + let mut minHeap: Option> = Some(Rc::new(RefCell::new(MinHeap { + size: 0, + capacity: capacity, + arr: Some(Rc::new(RefCell::new( + (0..(capacity as usize)) + .map(|_| >::default()) + .collect::>(), + ))), + next: 0, + alloc: Some(Rc::new(RefCell::new( + (0..10000_usize) + .map(|_| ::default()) + .collect::>(), + ))), }))); return minHeap.take(); } diff --git a/tests/unit/out/refcount/unique_ptr.rs b/tests/unit/out/refcount/unique_ptr.rs index cd2cc190a..0178f92e9 100644 --- a/tests/unit/out/refcount/unique_ptr.rs +++ b/tests/unit/out/refcount/unique_ptr.rs @@ -182,11 +182,8 @@ pub fn main() { fn main_0() -> i32 { let x: Value>> = Rc::new(RefCell::new(Some(Rc::new(RefCell::new(0))))); let safe_ptr: Value>> = - Rc::new(RefCell::new(Some(Rc::new(RefCell::new({ - let __tmp_0: Value = Rc::new(RefCell::new(SafePointer { - ptr: (*x.borrow_mut()).take(), - })); - SafePointer::move_from({ __tmp_0.as_pointer() }) + Rc::new(RefCell::new(Some(Rc::new(RefCell::new(SafePointer { + ptr: (*x.borrow_mut()).take(), }))))); ({ DoStuffWithSafePointer_0(safe_ptr.as_pointer()) }); assert!((({ Consume_1((*safe_ptr.borrow_mut()).take(),) }) == 60)); diff --git a/tests/unit/out/refcount/unique_ptr_nested.rs b/tests/unit/out/refcount/unique_ptr_nested.rs index f45fac3cb..a8f7dcbcb 100644 --- a/tests/unit/out/refcount/unique_ptr_nested.rs +++ b/tests/unit/out/refcount/unique_ptr_nested.rs @@ -33,11 +33,8 @@ pub fn main() { std::process::exit(main_0()); } fn main_0() -> i32 { - let mut o: Option> = Some(Rc::new(RefCell::new({ - let __tmp_0: Value = Rc::new(RefCell::new(Outer { - inner: Some(Rc::new(RefCell::new(Inner { x: 10, y: 20 }))), - })); - Outer::move_from({ __tmp_0.as_pointer() }) + let mut o: Option> = Some(Rc::new(RefCell::new(Outer { + inner: Some(Rc::new(RefCell::new(Inner { x: 10, y: 20 }))), }))); (*{ (*o.as_ref().unwrap().borrow()).inner.clone() } .as_ref() diff --git a/tests/unit/out/unsafe/elidable_iterator_copy_cxx11.rs b/tests/unit/out/unsafe/elidable_iterator_copy_cxx11.rs new file mode 100644 index 000000000..ddbf28195 --- /dev/null +++ b/tests/unit/out/unsafe/elidable_iterator_copy_cxx11.rs @@ -0,0 +1,36 @@ +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 v: Vec = Vec::new(); + { + let __a1 = 4; + v.push(__a1) + }; + { + let __a1 = 7; + v.push(__a1) + }; + let mut it: *mut i32 = { + let mut it = v.as_mut_ptr(); + while it != v.as_mut_ptr().add(v.len()) && *it != 7 { + it = it.add(1); + } + it + }; + assert!(it != v.as_mut_ptr().add(v.len())); + assert!(((*it) == (7))); + return 0; +} +pub unsafe fn __cpp2rust_init_globals() {} diff --git a/tests/unit/out/unsafe/huffman.rs b/tests/unit/out/unsafe/huffman.rs index bd29afe68..3aa308a59 100644 --- a/tests/unit/out/unsafe/huffman.rs +++ b/tests/unit/out/unsafe/huffman.rs @@ -145,23 +145,20 @@ impl MinHeap { } } pub unsafe fn AllocMinHeap_1(mut capacity: i32) -> Option> { - let mut minHeap: Option> = Some(Box::new({ - let mut __tmp_0: MinHeap = MinHeap { - size: 0, - capacity: capacity, - arr: Some( - (0..(capacity as usize)) - .map(|_| <*mut MinHeapNode>::default()) - .collect::>(), - ), - next: 0, - alloc: Some( - (0..10000_usize) - .map(|_| ::default()) - .collect::>(), - ), - }; - MinHeap::move_from({ &mut __tmp_0 }) + let mut minHeap: Option> = Some(Box::new(MinHeap { + size: 0, + capacity: capacity, + arr: Some( + (0..(capacity as usize)) + .map(|_| <*mut MinHeapNode>::default()) + .collect::>(), + ), + next: 0, + alloc: Some( + (0..10000_usize) + .map(|_| ::default()) + .collect::>(), + ), })); return minHeap.take(); } diff --git a/tests/unit/out/unsafe/unique_ptr.rs b/tests/unit/out/unsafe/unique_ptr.rs index 080296936..10145b902 100644 --- a/tests/unit/out/unsafe/unique_ptr.rs +++ b/tests/unit/out/unsafe/unique_ptr.rs @@ -160,10 +160,7 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut x: Option> = Some(Box::new(0)); - let mut safe_ptr: Option> = Some(Box::new({ - let mut __tmp_0: SafePointer = SafePointer { ptr: x.take() }; - SafePointer::move_from({ &mut __tmp_0 }) - })); + let mut safe_ptr: Option> = Some(Box::new(SafePointer { ptr: x.take() })); (unsafe { DoStuffWithSafePointer_0(&mut safe_ptr) }); assert!(((unsafe { Consume_1(safe_ptr.take(),) }) == (60))); return 0; diff --git a/tests/unit/out/unsafe/unique_ptr_nested.rs b/tests/unit/out/unsafe/unique_ptr_nested.rs index d63623a1a..02e0961fd 100644 --- a/tests/unit/out/unsafe/unique_ptr_nested.rs +++ b/tests/unit/out/unsafe/unique_ptr_nested.rs @@ -36,11 +36,8 @@ pub fn main() { } } unsafe fn main_0() -> i32 { - let mut o: Option> = Some(Box::new({ - let mut __tmp_0: Outer = Outer { - inner: Some(Box::new(Inner { x: 10, y: 20 })), - }; - Outer::move_from({ &mut __tmp_0 }) + let mut o: Option> = Some(Box::new(Outer { + inner: Some(Box::new(Inner { x: 10, y: 20 })), })); (*(*o.as_deref_mut().unwrap()).inner.as_deref_mut().unwrap()).x += 5; let mut sum: i32 = (((*(*o.as_deref_mut().unwrap()).inner.as_deref_mut().unwrap()).x)