Skip to content

Commit

Permalink
Revert "Try detecting mixed derive/derivative with Clone and `C…
Browse files Browse the repository at this point in the history
…opy`"

This reverts commit 4117fff.

As of rust 1.17, proc-macros don't get attributes other than their own
in the token stream they're fed.
See rust-lang/rust#39572
  • Loading branch information
glandium authored and mcarton committed Oct 20, 2018
1 parent 0d9930b commit c696dd6
Show file tree
Hide file tree
Showing 5 changed files with 7 additions and 83 deletions.
47 changes: 2 additions & 45 deletions src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,13 @@ pub struct InputClone {
bounds: Option<Vec<syn::WherePredicate>>,
/// Whether the implementation should have an explicit `clone_from`.
pub clone_from: bool,
/// Whether the `rustc_copy_clone_marker` was found.
pub rustc_copy_clone_marker: bool,
}

#[derive(Debug, Default)]
/// Represent the `derivative(Clone(…))` attributes on an input.
pub struct InputCopy {
/// The `bound` attribute if present and the corresponding bounds.
bounds: Option<Vec<syn::WherePredicate>>,
/// Whether the input also derive `Clone` (ie. `derive(Clone)`, but not `derivative(Clone)`)
derives_clone: bool,
}

#[derive(Debug, Default)]
Expand Down Expand Up @@ -215,50 +211,21 @@ impl Input {
for_all_attr! {
for (name, values) in attrs;
"Clone" => {
let mut clone = input.clone.take().unwrap_or_default();

clone.rustc_copy_clone_marker = attrs
.iter()
.filter_map(|attr| attr.parse_meta().ok())
.any(|meta| meta.name().to_string() == "rustc_copy_clone_marker");

match_attributes! {
let Some(clone) = input.clone;
for value in values;
"bound" => try!(parse_bound(&mut clone.bounds, opt_string_to_str!(value))),
"clone_from" => {
clone.clone_from = try!(parse_boolean_meta_item(&opt_string_to_str!(value), true, "clone_from"));
}
}

input.clone = Some(clone);
}
"Copy" => {
let mut copy = input.copy.take().unwrap_or_default();

for attr in attrs {
if let Ok(syn::Meta::List(syn::MetaList{
ident: ref name,
nested: ref traits,
..
})) = attr.parse_meta() {
fn is_clone(elem: &syn::NestedMeta) -> bool {
match *elem {
syn::NestedMeta::Meta(ref mi) => mi.name() == "Clone",
syn::NestedMeta::Literal(..) => false,
}
}
if name == "derive" && traits.iter().any(is_clone) {
copy.derives_clone = true;
}
}
}

match_attributes! {
let Some(copy) = input.copy;
for value in values;
"bound" => try!(parse_bound(&mut copy.bounds, opt_string_to_str!(value))),
}

input.copy = Some(copy);
}
"Debug" => {
match_attributes! {
Expand Down Expand Up @@ -325,10 +292,6 @@ impl Input {
.map_or(None, |d| d.bounds.as_ref().map(Vec::as_slice))
}

pub fn derives_clone(&self) -> bool {
self.copy.as_ref().map_or(false, |d| d.derives_clone)
}

pub fn debug_bound(&self) -> Option<&[syn::WherePredicate]> {
self.debug
.as_ref()
Expand Down Expand Up @@ -357,12 +320,6 @@ impl Input {
.map_or(None, |d| d.bounds.as_ref().map(Vec::as_slice))
}

pub fn rustc_copy_clone_marker(&self) -> bool {
self.clone
.as_ref()
.map_or(false, |d| d.rustc_copy_clone_marker)
}

pub fn partial_eq_bound(&self) -> Option<&[syn::WherePredicate]> {
self.partial_eq
.as_ref()
Expand Down
12 changes: 4 additions & 8 deletions src/clone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@ use syn;
use utils;

/// Derive `Copy` for `input`.
pub fn derive_copy(input: &ast::Input) -> Result<proc_macro2::TokenStream, String> {
pub fn derive_copy(input: &ast::Input) -> proc_macro2::TokenStream {
let name = &input.ident;

if input.attrs.derives_clone() {
return Err("`#[derivative(Copy)]` can't be used with `#[derive(Clone)]`".into());
}

let copy_trait_path = copy_trait_path();
let generics = utils::build_impl_generics(
input,
Expand All @@ -24,10 +20,10 @@ pub fn derive_copy(input: &ast::Input) -> Result<proc_macro2::TokenStream, Strin
);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

Ok(quote! {
quote! {
#[allow(unused_qualifications)]
impl #impl_generics #copy_trait_path for #name #ty_generics #where_clause {}
})
}
}

/// Derive `Clone` for `input`.
Expand All @@ -44,7 +40,7 @@ pub fn derive_clone(input: &ast::Input) -> proc_macro2::TokenStream {
);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

let is_copy = input.attrs.rustc_copy_clone_marker() || input.attrs.copy.is_some();
let is_copy = input.attrs.copy.is_some();
if is_copy && input.generics.type_params().count() == 0 {
quote! {
#[allow(unused_qualifications)]
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fn derive_impls(input: &ast::Input) -> Result<proc_macro2::TokenStream, String>
tokens.extend(clone::derive_clone(input));
}
if input.attrs.copy.is_some() {
tokens.extend(clone::derive_copy(input)?);
tokens.extend(clone::derive_copy(input));
}
if input.attrs.debug.is_some() {
tokens.extend(debug::derive(input));
Expand Down
12 changes: 0 additions & 12 deletions tests/compile-fail/derive-copy-clone.rs

This file was deleted.

17 changes: 0 additions & 17 deletions tests/rustc-deriving-copyclone.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,6 @@ struct OurOur1(Liar);
#[derivative(Clone, Copy)]
struct OurOur2(Liar);

#[derive(Copy)]
#[derive(Derivative)]
#[derivative(Clone)]
struct TheirOur1(Liar);
#[derive(Copy)]
#[derive(Derivative)]
#[derivative(Clone)]
struct TheirOur2(Liar);

#[test]
fn main() {
let _ = TheirTheir(Liar).clone();
Expand All @@ -62,12 +53,4 @@ fn main() {
assert!(!CLONED.load(Ordering::SeqCst), "OurOur1");
let _ = OurOur2(Liar).clone();
assert!(!CLONED.load(Ordering::SeqCst), "OurOur2");

// Ideally this would work the same, just testing that the behaviour does not change:
CLONED.store(false, Ordering::SeqCst);
let _ = TheirOur1(Liar).clone();
assert!(CLONED.load(Ordering::SeqCst), "TheirOur1");
CLONED.store(false, Ordering::SeqCst);
let _ = TheirOur2(Liar).clone();
assert!(CLONED.load(Ordering::SeqCst), "TheirOur2");
}

0 comments on commit c696dd6

Please sign in to comment.