summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <me@emiliocobos.me>2016-04-16 05:11:39 +0200
committerEmilio Cobos Álvarez <me@emiliocobos.me>2016-04-16 05:11:39 +0200
commit4a8fea550823afe97bd8b64c9aaf2171a9d4dcc2 (patch)
tree3dd307dbf8e30a3571f2722f3f83f46a6cf15ce9
parent69f5eacbb78f6dab1f73dedd71479410fb5a689a (diff)
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.
-rw-r--r--src/gen.rs4
-rw-r--r--src/types.rs41
-rw-r--r--tests/expectations/class_nested.rs2
3 files changed, 43 insertions, 4 deletions
diff --git a/src/gen.rs b/src/gen.rs
index aa501dfd..c8144c00 100644
--- a/src/gen.rs
+++ b/src/gen.rs
@@ -827,7 +827,9 @@ fn comp_attrs(ctx: &GenCtx, ci: &CompInfo, name: &str, extra: &mut Vec<P<ast::It
let attr = ctx.ext_cx.ident_of(attr);
attrs.push(quote_attr!(&ctx.ext_cx, #[$attr]));
}
- } else {
+ }
+
+ if ci.can_derive_copy() {
derives.push("Copy");
// TODO: make mk_clone_impl work for template arguments,
diff --git a/src/types.rs b/src/types.rs
index 0d2fc8b2..120a455b 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -235,6 +235,16 @@ impl Type {
}
}
+ fn can_derive_copy(&self) -> bool {
+ !self.is_opaque() && match *self {
+ TVoid => false,
+ TArray(ref t, _, _) => t.can_derive_copy(),
+ TNamed(ref ti) => ti.borrow().ty.can_derive_copy(),
+ TComp(ref comp) => comp.borrow().can_derive_copy(),
+ _ => true,
+ }
+ }
+
pub fn is_opaque(&self) -> bool {
match *self {
TArray(ref t, _, _) => t.is_opaque(),
@@ -475,7 +485,7 @@ impl CompInfo {
// not having destructor.
//
// This is unfortunate, but...
- !self.args.is_empty() ||
+ self.args.iter().any(|t| t.has_destructor()) ||
self.members.iter().enumerate().any(|(index, m)| match *m {
CompMember::Field(ref f) |
CompMember::CompField(_, ref f) => {
@@ -492,6 +502,33 @@ impl CompInfo {
}
}
+ // We only
+ pub fn can_derive_copy(&self) -> bool {
+ match self.kind {
+ CompKind::Union => true,
+ CompKind::Struct => {
+ if self.has_destructor() {
+ return false;
+ }
+
+ // Anything not destructible and with template parameters
+ // is copiable
+ if self.args.is_empty() {
+ return true;
+ }
+
+ // With template args, use a safe subset of the types,
+ // since copyability depends on the types itself.
+ self.ref_template.as_ref().map_or(true, |t| t.can_derive_copy()) &&
+ self.members.iter().all(|m| match *m {
+ CompMember::Field(ref f) |
+ CompMember::CompField(_, ref f) => f.ty.can_derive_copy(),
+ _ => true,
+ })
+ }
+ }
+ }
+
pub fn is_translatable(&self) -> bool {
match self.kind {
CompKind::Union => true,
@@ -504,7 +541,7 @@ impl CompInfo {
impl fmt::Debug for CompInfo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- self.name.fmt(f)
+ write!(f, "CompInfo({}, ref: {:?}, args: {:?}, members: {:?}", self.name, self.ref_template, self.args, self.members)
}
}
diff --git a/tests/expectations/class_nested.rs b/tests/expectations/class_nested.rs
index 9c604497..ba23c3d3 100644
--- a/tests/expectations/class_nested.rs
+++ b/tests/expectations/class_nested.rs
@@ -50,7 +50,7 @@ pub struct Struct_Templated<T> {
pub member: T,
}
#[repr(C)]
-#[derive(Debug)]
+#[derive(Debug, Copy, Clone)]
pub struct Struct_Templated_Templated_inner<T> {
pub member_ptr: *mut T,
}