Skip to content

Commit 4a8fea5

Browse files
committed
gen: Derive Copy for templates that allow it
It broke for arrays if we try to do it by default, but this seems to work pretty well.
1 parent 69f5eac commit 4a8fea5

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

src/gen.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,9 @@ fn comp_attrs(ctx: &GenCtx, ci: &CompInfo, name: &str, extra: &mut Vec<P<ast::It
827827
let attr = ctx.ext_cx.ident_of(attr);
828828
attrs.push(quote_attr!(&ctx.ext_cx, #[$attr]));
829829
}
830-
} else {
830+
}
831+
832+
if ci.can_derive_copy() {
831833
derives.push("Copy");
832834

833835
// TODO: make mk_clone_impl work for template arguments,

src/types.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,16 @@ impl Type {
235235
}
236236
}
237237

238+
fn can_derive_copy(&self) -> bool {
239+
!self.is_opaque() && match *self {
240+
TVoid => false,
241+
TArray(ref t, _, _) => t.can_derive_copy(),
242+
TNamed(ref ti) => ti.borrow().ty.can_derive_copy(),
243+
TComp(ref comp) => comp.borrow().can_derive_copy(),
244+
_ => true,
245+
}
246+
}
247+
238248
pub fn is_opaque(&self) -> bool {
239249
match *self {
240250
TArray(ref t, _, _) => t.is_opaque(),
@@ -475,7 +485,7 @@ impl CompInfo {
475485
// not having destructor.
476486
//
477487
// This is unfortunate, but...
478-
!self.args.is_empty() ||
488+
self.args.iter().any(|t| t.has_destructor()) ||
479489
self.members.iter().enumerate().any(|(index, m)| match *m {
480490
CompMember::Field(ref f) |
481491
CompMember::CompField(_, ref f) => {
@@ -492,6 +502,33 @@ impl CompInfo {
492502
}
493503
}
494504

505+
// We only
506+
pub fn can_derive_copy(&self) -> bool {
507+
match self.kind {
508+
CompKind::Union => true,
509+
CompKind::Struct => {
510+
if self.has_destructor() {
511+
return false;
512+
}
513+
514+
// Anything not destructible and with template parameters
515+
// is copiable
516+
if self.args.is_empty() {
517+
return true;
518+
}
519+
520+
// With template args, use a safe subset of the types,
521+
// since copyability depends on the types itself.
522+
self.ref_template.as_ref().map_or(true, |t| t.can_derive_copy()) &&
523+
self.members.iter().all(|m| match *m {
524+
CompMember::Field(ref f) |
525+
CompMember::CompField(_, ref f) => f.ty.can_derive_copy(),
526+
_ => true,
527+
})
528+
}
529+
}
530+
}
531+
495532
pub fn is_translatable(&self) -> bool {
496533
match self.kind {
497534
CompKind::Union => true,
@@ -504,7 +541,7 @@ impl CompInfo {
504541

505542
impl fmt::Debug for CompInfo {
506543
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
507-
self.name.fmt(f)
544+
write!(f, "CompInfo({}, ref: {:?}, args: {:?}, members: {:?}", self.name, self.ref_template, self.args, self.members)
508545
}
509546
}
510547

tests/expectations/class_nested.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ pub struct Struct_Templated<T> {
5050
pub member: T,
5151
}
5252
#[repr(C)]
53-
#[derive(Debug)]
53+
#[derive(Debug, Copy, Clone)]
5454
pub struct Struct_Templated_Templated_inner<T> {
5555
pub member_ptr: *mut T,
5656
}

0 commit comments

Comments
 (0)