Skip to content

Commit d6fa5c5

Browse files
committed
Use implicit move ctor when copy ctor is not aavilable
1 parent 9f9eac0 commit d6fa5c5

5 files changed

Lines changed: 37 additions & 27 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4271,13 +4271,11 @@ Converter::GetStructAttributes(const clang::RecordDecl *decl) {
42714271

42724272
std::vector<const char *> struct_attrs;
42734273

4274-
bool derives_clone =
4275-
HasDefaultedCopyConstructor(decl) && RecordImplementsClone(decl);
4276-
if (derives_clone && RecordHasCopyableFields(decl)) {
4274+
if (HasDefaultedCopyConstructor(decl) && RecordHasCopyableFields(decl)) {
42774275
struct_attrs.emplace_back("Copy");
42784276
}
42794277

4280-
if (derives_clone) {
4278+
if (HasDefaultedCopyConstructor(decl)) {
42814279
struct_attrs.emplace_back("Clone");
42824280
}
42834281

@@ -4764,16 +4762,8 @@ void Converter::AddCloneTrait(const clang::RecordDecl *decl) {
47644762
}
47654763

47664764
bool Converter::RecordImplementsClone(const clang::RecordDecl *decl) {
4767-
if (GetUserDefinedCopyConstructor(decl)) {
4768-
return HasCallableCopyConstructor(decl);
4769-
}
4770-
return HasDefaultedCopyConstructor(decl) &&
4771-
std::ranges::all_of(decl->fields(), [&](const clang::FieldDecl *f) {
4772-
auto *record =
4773-
ctx_.getBaseElementType(f->getType())->getAsCXXRecordDecl();
4774-
return !record || !IsUserDefinedDecl(record) ||
4775-
RecordImplementsClone(record);
4776-
});
4765+
return HasDefaultedCopyConstructor(decl) ||
4766+
GetUserDefinedCopyConstructor(decl) != nullptr;
47774767
}
47784768

47794769
void Converter::AddDefaultTraitForUnion(const clang::RecordDecl *decl) {

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -502,17 +502,28 @@ GetUserDefinedCopyConstructor(const clang::RecordDecl *decl) {
502502
return nullptr;
503503
}
504504

505+
static bool FieldsHaveCallableCopyConstructors(const clang::RecordDecl *decl) {
506+
auto &ctx = decl->getASTContext();
507+
return std::ranges::all_of(decl->fields(), [&](const clang::FieldDecl *f) {
508+
auto *record = ctx.getBaseElementType(f->getType())->getAsCXXRecordDecl();
509+
return !record || !IsUserDefinedDecl(record) ||
510+
HasCallableCopyConstructor(record);
511+
});
512+
}
513+
505514
bool HasDefaultedCopyConstructor(const clang::RecordDecl *decl) {
506515
auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl);
507516
if (!cxx) {
508517
return true;
509518
}
510519
for (const auto *ctor : cxx->ctors()) {
511520
if (ctor->isCopyConstructor()) {
512-
return !ctor->isUserProvided() && !ctor->isDeleted();
521+
return !ctor->isUserProvided() && !ctor->isDeleted() &&
522+
FieldsHaveCallableCopyConstructors(cxx);
513523
}
514524
}
515-
return !cxx->defaultedCopyConstructorIsDeleted();
525+
return !cxx->defaultedCopyConstructorIsDeleted() &&
526+
FieldsHaveCallableCopyConstructors(cxx);
516527
}
517528

518529
bool RecordHasOnlyReferenceFields(const clang::RecordDecl *decl) {
@@ -543,7 +554,7 @@ bool HasCallableCopyConstructor(const clang::RecordDecl *decl) {
543554
return true;
544555
}
545556
if (!cxx->hasUserDeclaredCopyConstructor()) {
546-
return !cxx->defaultedCopyConstructorIsDeleted();
557+
return HasDefaultedCopyConstructor(cxx);
547558
}
548559
for (const auto *ctor : cxx->ctors()) {
549560
if (ctor->isCopyConstructor() && !ctor->isDeleted() &&

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -603,13 +603,7 @@ bool ConverterRefCount::RecordImplementsClone(const clang::RecordDecl *decl) {
603603
return true;
604604
}
605605
return !clang::isa<clang::CXXRecordDecl>(decl) ||
606-
(HasCallableCopyConstructor(decl) &&
607-
std::ranges::all_of(decl->fields(), [&](const clang::FieldDecl *f) {
608-
auto *record =
609-
ctx_.getBaseElementType(f->getType())->getAsCXXRecordDecl();
610-
return !record || !IsUserDefinedDecl(record) ||
611-
RecordImplementsClone(record);
612-
}));
606+
HasCallableCopyConstructor(decl);
613607
}
614608

615609
// Bases are translated to traits, so they hold no state of the struct; they
@@ -629,7 +623,7 @@ bool ConverterRefCount::RecordDerivesClone(const clang::RecordDecl *decl) {
629623
// The copy of a struct copies each field, which a derived Clone does too,
630624
// except for Values, which it shares.
631625
auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl);
632-
if (decl->isUnion() || (cxx && (!RecordImplementsClone(cxx) ||
626+
if (decl->isUnion() || (cxx && (!HasCallableCopyConstructor(cxx) ||
633627
GetUserDefinedCopyConstructor(cxx) ||
634628
!HasDefaultedBaseCopies(cxx)))) {
635629
return false;

‎tests/unit/out/refcount/copy_ctor.rs‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,13 @@ pub struct Owner {
135135
#[byte_size(4)]
136136
pub box_: Box_int_,
137137
}
138+
impl Owner {
139+
pub fn move_from(_a0: Ptr<Owner>) -> Self {
140+
Self {
141+
box_: Box_int_::move_from({ field_ptr!(_a0, box_) }),
142+
}
143+
}
144+
}
138145
pub fn by_value_1(mut c: Counted) -> i32 {
139146
return c.v;
140147
}
@@ -203,7 +210,7 @@ fn main_0() -> i32 {
203210
let o: Value<Owner> = Rc::new(RefCell::new(Owner {
204211
box_: Box_int_::new({ 3 }),
205212
}));
206-
let mut o2: Owner = (*o.borrow()).clone();
213+
let mut o2: Owner = Owner::move_from({ o.as_pointer() });
207214
assert!((o2.box_.val == 3));
208215
let n: Value<NonConst> = Rc::new(RefCell::new(NonConst::new()));
209216
let mut n1: NonConst = NonConst::new_1({ n.as_pointer() });

‎tests/unit/out/unsafe/copy_ctor.rs‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ impl Box_int_ {
108108
pub struct Owner {
109109
pub box_: Box_int_,
110110
}
111+
impl Owner {
112+
pub unsafe fn move_from(_a0: *mut Owner) -> Self {
113+
let mut this = Self {
114+
box_: Box_int_::move_from({ &mut (*_a0).box_ }),
115+
};
116+
this
117+
}
118+
}
111119
pub unsafe fn by_value_1(mut c: Counted) -> i32 {
112120
return c.v;
113121
}
@@ -164,7 +172,7 @@ unsafe fn main_0() -> i32 {
164172
let mut o: Owner = Owner {
165173
box_: Box_int_::new({ 3 }),
166174
};
167-
let mut o2: Owner = o.clone();
175+
let mut o2: Owner = Owner::move_from({ &mut o });
168176
assert!(((o2.box_.val) == (3)));
169177
let mut n: NonConst = NonConst::new();
170178
let mut n1: NonConst = NonConst::new_1({ &mut n });

0 commit comments

Comments
 (0)