Skip to content

Commit e8cf37a

Browse files
committed
Derive Clone when all fields are references
1 parent b5dd144 commit e8cf37a

20 files changed

Lines changed: 88 additions & 143 deletions

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,15 @@ bool HasDefaultedCopyConstructor(const clang::RecordDecl *decl) {
352352
return !cxx->defaultedCopyConstructorIsDeleted();
353353
}
354354

355+
bool RecordHasOnlyReferenceFields(const clang::RecordDecl *decl) {
356+
for (auto *field : decl->fields()) {
357+
if (!field->getType()->isReferenceType()) {
358+
return false;
359+
}
360+
}
361+
return true;
362+
}
363+
355364
bool HasDefaultedCopyAssignment(const clang::RecordDecl *decl) {
356365
auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl);
357366
if (!cxx) {

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ bool HasCallableCopyConstructor(const clang::RecordDecl *decl);
8787

8888
bool HasDefaultedCopyConstructor(const clang::RecordDecl *decl);
8989

90+
bool RecordHasOnlyReferenceFields(const clang::RecordDecl *decl);
91+
9092
bool HasDefaultedCopyAssignment(const clang::RecordDecl *decl);
9193

9294
bool IsRValueConvertingConstructor(const clang::CXXConstructorDecl *ctor);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,9 @@ void ConverterRefCount::AddCloneTrait(const clang::RecordDecl *decl) {
480480
return;
481481
}
482482

483+
if (HasDefaultedCopyConstructor(decl) && RecordHasOnlyReferenceFields(decl)) {
484+
return;
485+
}
483486
auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl);
484487
if (!cxx) {
485488
StrCat(keyword::kImpl, "Clone for", record_name);
@@ -2115,6 +2118,10 @@ ConverterRefCount::GetStructAttributes(const clang::RecordDecl *decl) {
21152118
return attrs;
21162119
}
21172120

2121+
if (HasDefaultedCopyConstructor(decl) && RecordHasOnlyReferenceFields(decl)) {
2122+
attrs.emplace_back("Clone");
2123+
}
2124+
21182125
if (RecordDerivesDefault(decl)) {
21192126
attrs.emplace_back("Default");
21202127
}

‎tests/ub/out/refcount/ctor_ref_member.rs‎

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::io::prelude::*;
66
use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
9-
#[derive(Default)]
9+
#[derive(Clone, Default)]
1010
pub struct S {
1111
pub r: Ptr<i32>,
1212
}
@@ -17,15 +17,6 @@ impl S {
1717
Rc::try_unwrap(__this).ok().unwrap().into_inner()
1818
}
1919
}
20-
impl Clone for S {
21-
fn clone(&self) -> Self {
22-
let __this: Value<S> = Rc::new(RefCell::new(Self {
23-
r: (self.r).clone(),
24-
}));
25-
let this: Ptr<S> = __this.as_pointer();
26-
Rc::try_unwrap(__this).ok().unwrap().into_inner()
27-
}
28-
}
2920
impl ByteRepr for S {}
3021
pub fn main() {
3122
__cpp2rust_init_globals();

‎tests/ub/out/refcount/ub6.rs‎

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,11 @@ use std::io::prelude::*;
66
use std::io::{Read, Seek, Write};
77
use std::os::fd::AsFd;
88
use std::rc::{Rc, Weak};
9-
#[derive(Default)]
9+
#[derive(Clone, Default)]
1010
pub struct Pair {
1111
pub x1: Ptr<i32>,
1212
pub x2: Ptr<i32>,
1313
}
14-
impl Clone for Pair {
15-
fn clone(&self) -> Self {
16-
let __this: Value<Pair> = Rc::new(RefCell::new(Self {
17-
x1: (self.x1).clone(),
18-
x2: (self.x2).clone(),
19-
}));
20-
let this: Ptr<Pair> = __this.as_pointer();
21-
Rc::try_unwrap(__this).ok().unwrap().into_inner()
22-
}
23-
}
2414
impl ByteRepr for Pair {}
2515
pub fn mkPair_0(x1: Ptr<i32>, x2: Ptr<i32>) -> Pair {
2616
return Pair {

‎tests/unit/clone_vs_move.cpp‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ struct Foo {
1616
Bar bar;
1717
};
1818

19+
struct Refs {
20+
int &a;
21+
int &b;
22+
};
23+
1924
int main() {
2025
int x1 = 1;
2126
int x2 = x1;
@@ -182,5 +187,15 @@ int main() {
182187
assert(v2[i] == i + 1);
183188
}
184189

190+
int ra = 1, rb = 2;
191+
Refs r1{ra, rb};
192+
Refs r2 = r1;
193+
r2.a = 10;
194+
++r2.b;
195+
assert(ra == 10);
196+
assert(rb == 3);
197+
assert(r1.a == 10);
198+
assert(r1.b == 3);
199+
185200
return 0;
186201
}

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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ impl Default for Foo {
6969
}
7070
}
7171
impl ByteRepr for Foo {}
72+
#[derive(Clone, Default)]
73+
pub struct Refs {
74+
pub a: Ptr<i32>,
75+
pub b: Ptr<i32>,
76+
}
77+
impl ByteRepr for Refs {}
7278
pub fn main() {
7379
__cpp2rust_init_globals();
7480
std::process::exit(main_0());
@@ -507,6 +513,19 @@ fn main_0() -> i32 {
507513
);
508514
(*i.borrow_mut()).prefix_inc();
509515
}
516+
let ra: Value<i32> = Rc::new(RefCell::new(1));
517+
let rb: Value<i32> = Rc::new(RefCell::new(2));
518+
let r1: Value<Refs> = Rc::new(RefCell::new(Refs {
519+
a: ra.as_pointer(),
520+
b: rb.as_pointer(),
521+
}));
522+
let r2: Value<Refs> = Rc::new(RefCell::new((*r1.borrow()).clone()));
523+
(*r2.borrow()).a.write(10);
524+
(*r2.borrow()).b.with_mut(|__v| __v.prefix_inc());
525+
assert!(((*ra.borrow()) == 10));
526+
assert!(((*rb.borrow()) == 3));
527+
assert!((((*r1.borrow()).a.read()) == 10));
528+
assert!((((*r1.borrow()).b.read()) == 3));
510529
return 0;
511530
}
512531
pub fn __cpp2rust_init_globals() {}

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

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,10 @@ impl ByteRepr for X1 {
4343
}
4444
}
4545
}
46-
#[derive(Default)]
46+
#[derive(Clone, Default)]
4747
pub struct X2 {
4848
pub v: Ptr<X1>,
4949
}
50-
impl Clone for X2 {
51-
fn clone(&self) -> Self {
52-
let __this: Value<X2> = Rc::new(RefCell::new(Self {
53-
v: (self.v).clone(),
54-
}));
55-
let this: Ptr<X2> = __this.as_pointer();
56-
Rc::try_unwrap(__this).ok().unwrap().into_inner()
57-
}
58-
}
5950
impl ByteRepr for X2 {}
6051
#[derive(Default)]
6152
pub struct X3 {

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,8 @@ use std::rc::{Rc, Weak};
99
thread_local!(
1010
pub static global_0: Value<i32> = Rc::new(RefCell::new(0));
1111
);
12-
#[derive(Default)]
12+
#[derive(Clone, Default)]
1313
pub struct S {}
14-
impl Clone for S {
15-
fn clone(&self) -> Self {
16-
let __this: Value<S> = Rc::new(RefCell::new(Self {}));
17-
let this: Ptr<S> = __this.as_pointer();
18-
Rc::try_unwrap(__this).ok().unwrap().into_inner()
19-
}
20-
}
2114
impl ByteRepr for S {
2215
fn byte_size() -> usize {
2316
1

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

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,8 @@ pub fn foo_3(x: Ptr<i32>, y: Ptr<i32>, z: Ptr<i32>) -> i32 {
3636
pub fn bar_4(x: Ptr<i32>) -> i32 {
3737
return (x.read());
3838
}
39-
#[derive(Default)]
39+
#[derive(Clone, Default)]
4040
pub struct Foo {}
41-
impl Clone for Foo {
42-
fn clone(&self) -> Self {
43-
let __this: Value<Foo> = Rc::new(RefCell::new(Self {}));
44-
let this: Ptr<Foo> = __this.as_pointer();
45-
Rc::try_unwrap(__this).ok().unwrap().into_inner()
46-
}
47-
}
4841
impl ByteRepr for Foo {
4942
fn byte_size() -> usize {
5043
1

0 commit comments

Comments
 (0)