Expand derives manually where allowed
diff --git a/macro/src/derive.rs b/macro/src/derive.rs
deleted file mode 100644
index 1abc5da..0000000
--- a/macro/src/derive.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use crate::syntax::Derive;
-use proc_macro2::TokenStream;
-use quote::{quote, ToTokens};
-
-pub struct DeriveAttribute<'a>(pub &'a [Derive]);
-
-impl<'a> ToTokens for DeriveAttribute<'a> {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- if !self.0.is_empty() {
- let derives = self.0;
- tokens.extend(quote!(#[derive(#(#derives),*)]));
- }
- }
-}
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index c735483..92551e6 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -1,11 +1,10 @@
-use crate::derive::DeriveAttribute;
use crate::syntax::atom::Atom::{self, *};
use crate::syntax::file::Module;
use crate::syntax::report::Errors;
use crate::syntax::symbol::Symbol;
use crate::syntax::{
- self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Signature,
- Struct, Type, TypeAlias, Types,
+ self, check, mangle, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName,
+ Signature, Struct, Type, TypeAlias, Types,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -127,7 +126,6 @@
fn expand_struct(strct: &Struct) -> TokenStream {
let ident = &strct.name.rust;
let doc = &strct.doc;
- let derives = DeriveAttribute(&strct.derives);
let type_id = type_id(&strct.name);
let fields = strct.fields.iter().map(|field| {
// This span on the pub makes "private type in public interface" errors
@@ -136,9 +134,8 @@
quote!(#vis #field)
});
- quote! {
+ let mut expanded = quote! {
#doc
- #derives
#[repr(C)]
pub struct #ident {
#(#fields,)*
@@ -148,7 +145,37 @@
type Id = #type_id;
type Kind = ::cxx::kind::Trivial;
}
+ };
+
+ let is_copy = strct.derives.contains(&Derive::Copy);
+ for derive in &strct.derives {
+ match derive {
+ Derive::Copy => {
+ expanded.extend(quote! {
+ impl ::std::marker::Copy for #ident {}
+ });
+ }
+ Derive::Clone => {
+ let body = if is_copy {
+ quote!(*self)
+ } else {
+ let fields = strct.fields.iter().map(|field| &field.ident);
+ quote!(#ident {
+ #(#fields: ::std::clone::Clone::clone(&self.#fields),)*
+ })
+ };
+ expanded.extend(quote! {
+ impl ::std::clone::Clone for #ident {
+ fn clone(&self) -> Self {
+ #body
+ }
+ }
+ });
+ }
+ }
}
+
+ expanded
}
fn expand_enum(enm: &Enum) -> TokenStream {
@@ -166,7 +193,7 @@
quote! {
#doc
- #[derive(Copy, Clone, PartialEq, Eq)]
+ #[derive(PartialEq, Eq)] // required to be derived in order to be usable in patterns
#[repr(transparent)]
pub struct #ident {
pub repr: #repr,
@@ -181,6 +208,14 @@
type Id = #type_id;
type Kind = ::cxx::kind::Trivial;
}
+
+ impl ::std::marker::Copy for #ident {}
+
+ impl ::std::clone::Clone for #ident {
+ fn clone(&self) -> Self {
+ *self
+ }
+ }
}
}
diff --git a/macro/src/lib.rs b/macro/src/lib.rs
index 1de7e6c..6285451 100644
--- a/macro/src/lib.rs
+++ b/macro/src/lib.rs
@@ -10,7 +10,6 @@
extern crate proc_macro;
-mod derive;
mod expand;
mod syntax;
mod type_id;
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 435aa20..855e80f 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -15,12 +15,3 @@
}
}
}
-
-impl AsRef<str> for Derive {
- fn as_ref(&self) -> &str {
- match self {
- Derive::Clone => "Clone",
- Derive::Copy => "Copy",
- }
- }
-}
diff --git a/syntax/tokens.rs b/syntax/tokens.rs
index d450f73..29899a9 100644
--- a/syntax/tokens.rs
+++ b/syntax/tokens.rs
@@ -1,7 +1,7 @@
use crate::syntax::atom::Atom::*;
use crate::syntax::{
- Array, Atom, Derive, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName,
- Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var,
+ Array, Atom, Enum, ExternFn, ExternType, Impl, Receiver, Ref, ResolvableName, Signature,
+ SliceRef, Struct, Ty1, Type, TypeAlias, Var,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote_spanned, ToTokens};
@@ -93,12 +93,6 @@
}
}
-impl ToTokens for Derive {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- Ident::new(self.as_ref(), Span::call_site()).to_tokens(tokens);
- }
-}
-
impl ToTokens for Atom {
fn to_tokens(&self, tokens: &mut TokenStream) {
Ident::new(self.as_ref(), Span::call_site()).to_tokens(tokens);
diff --git a/tests/ui/derive_duplicate.stderr b/tests/ui/derive_duplicate.stderr
index e0450e2..0d5de2c 100644
--- a/tests/ui/derive_duplicate.stderr
+++ b/tests/ui/derive_duplicate.stderr
@@ -7,4 +7,4 @@
| first implementation here
| conflicting implementation for `ffi::Struct`
|
- = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
+ = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)