diff options
author | Emilio Cobos Álvarez <me@emiliocobos.me> | 2016-04-16 05:11:39 +0200 |
---|---|---|
committer | Emilio Cobos Álvarez <me@emiliocobos.me> | 2016-04-16 05:11:39 +0200 |
commit | 4a8fea550823afe97bd8b64c9aaf2171a9d4dcc2 (patch) | |
tree | 3dd307dbf8e30a3571f2722f3f83f46a6cf15ce9 | |
parent | 69f5eacbb78f6dab1f73dedd71479410fb5a689a (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.rs | 4 | ||||
-rw-r--r-- | src/types.rs | 41 | ||||
-rw-r--r-- | tests/expectations/class_nested.rs | 2 |
3 files changed, 43 insertions, 4 deletions
@@ -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, } |