Preserve span on Derive trait impls
diff --git a/macro/src/expand.rs b/macro/src/expand.rs
index 92551e6..5bac706 100644
--- a/macro/src/expand.rs
+++ b/macro/src/expand.rs
@@ -3,8 +3,8 @@
use crate::syntax::report::Errors;
use crate::syntax::symbol::Symbol;
use crate::syntax::{
- self, check, mangle, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName,
- Signature, Struct, Type, TypeAlias, Types,
+ self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Signature,
+ Struct, Trait, Type, TypeAlias, Types,
};
use proc_macro2::{Ident, Span, TokenStream};
use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -147,15 +147,18 @@
}
};
- let is_copy = strct.derives.contains(&Derive::Copy);
+ let is_copy = strct
+ .derives
+ .iter()
+ .any(|derive| derive.what == Trait::Copy);
for derive in &strct.derives {
- match derive {
- Derive::Copy => {
- expanded.extend(quote! {
+ match derive.what {
+ Trait::Copy => {
+ expanded.extend(quote_spanned! {derive.span=>
impl ::std::marker::Copy for #ident {}
});
}
- Derive::Clone => {
+ Trait::Clone => {
let body = if is_copy {
quote!(*self)
} else {
@@ -164,7 +167,7 @@
#(#fields: ::std::clone::Clone::clone(&self.#fields),)*
})
};
- expanded.extend(quote! {
+ expanded.extend(quote_spanned! {derive.span=>
impl ::std::clone::Clone for #ident {
fn clone(&self) -> Self {
#body
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 855e80f..501dd61 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -1,17 +1,31 @@
-use proc_macro2::Ident;
+use proc_macro2::{Ident, Span};
+
+#[derive(Copy, Clone)]
+pub struct Derive {
+ pub what: Trait,
+ pub span: Span,
+}
#[derive(Copy, Clone, PartialEq)]
-pub enum Derive {
+pub enum Trait {
Clone,
Copy,
}
impl Derive {
pub fn from(ident: &Ident) -> Option<Self> {
- match ident.to_string().as_str() {
- "Clone" => Some(Derive::Clone),
- "Copy" => Some(Derive::Copy),
- _ => None,
- }
+ let what = match ident.to_string().as_str() {
+ "Clone" => Trait::Clone,
+ "Copy" => Trait::Copy,
+ _ => return None,
+ };
+ let span = ident.span();
+ Some(Derive { what, span })
+ }
+}
+
+impl PartialEq<Trait> for Derive {
+ fn eq(&self, other: &Trait) -> bool {
+ self.what == *other
}
}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 69b77bc..17b290a 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -33,7 +33,7 @@
use syn::{Expr, Generics, Lifetime, LitInt, Token, Type as RustType};
pub use self::atom::Atom;
-pub use self::derive::Derive;
+pub use self::derive::{Derive, Trait};
pub use self::doc::Doc;
pub use self::parse::parse_items;
pub use self::types::Types;
diff --git a/syntax/types.rs b/syntax/types.rs
index 8c628b3..5fe63ff 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -3,7 +3,7 @@
use crate::syntax::report::Errors;
use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
use crate::syntax::{
- toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
+ toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Trait, Type,
TypeAlias,
};
use proc_macro2::Ident;
@@ -261,7 +261,7 @@
pub fn is_pod(&self, strct: &Struct) -> bool {
for derive in &strct.derives {
- if *derive == Derive::Copy {
+ if derive.what == Trait::Copy {
return true;
}
}
diff --git a/tests/ui/derive_duplicate.stderr b/tests/ui/derive_duplicate.stderr
index 0d5de2c..4eefc24 100644
--- a/tests/ui/derive_duplicate.stderr
+++ b/tests/ui/derive_duplicate.stderr
@@ -1,10 +1,7 @@
error[E0119]: conflicting implementations of trait `std::clone::Clone` for type `ffi::Struct`:
- --> $DIR/derive_duplicate.rs:1:1
+ --> $DIR/derive_duplicate.rs:3:21
|
-1 | #[cxx::bridge]
- | ^^^^^^^^^^^^^^
- | |
- | first implementation here
- | conflicting implementation for `ffi::Struct`
- |
- = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)
+3 | #[derive(Clone, Clone)]
+ | ----- ^^^^^ conflicting implementation for `ffi::Struct`
+ | |
+ | first implementation here