diff --git a/src/gc-arena-derive/src/lib.rs b/src/gc-arena-derive/src/lib.rs index 4a6ede14..c91494c2 100644 --- a/src/gc-arena-derive/src/lib.rs +++ b/src/gc-arena-derive/src/lib.rs @@ -1,5 +1,5 @@ use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; +use quote::{quote, quote_spanned, ToTokens}; use syn::spanned::Spanned; use synstructure::{decl_derive, AddBounds}; @@ -160,12 +160,20 @@ fn collect_derive(mut s: synstructure::Structure) -> TokenStream { for v in s.variants() { for b in v.bindings() { let ty = &b.ast().ty; - quote!(|| <#ty as gc_arena::Collect>::needs_trace()) - .to_tokens(&mut needs_trace_body); + quote_spanned!(b.ast().span()=> + || <#ty as gc_arena::Collect>::needs_trace() + ).to_tokens(&mut needs_trace_body); } } // Likewise, this will skip any fields that have `#[collect(require_static)]` - let trace_body = s.each(|bi| quote!(gc_arena::Collect::trace(#bi, cc))); + let trace_body = s.each(|bi| { + // Make sure to only use `quote_spanned` on the method call + // tokens - we want to use the call site span for the `cc` identifier + let trace_method = quote_spanned!(bi.ast().span()=> + gc_arena::Collect::trace + ); + quote!(#trace_method (#bi, cc)) + }); s.clone().add_bounds(AddBounds::Fields).gen_impl(quote! { gen unsafe impl gc_arena::Collect for @Self #where_clause { diff --git a/src/gc-arena/tests/ui/bad_collect_bound.rs b/src/gc-arena/tests/ui/bad_collect_bound.rs new file mode 100644 index 00000000..ef08c9c3 --- /dev/null +++ b/src/gc-arena/tests/ui/bad_collect_bound.rs @@ -0,0 +1,11 @@ +use gc_arena::Collect; + +struct NotCollect; + +#[derive(Collect)] +#[collect(no_drop)] +struct MyStruct { + field: NotCollect +} + +fn main() {} diff --git a/src/gc-arena/tests/ui/bad_collect_bound.stderr b/src/gc-arena/tests/ui/bad_collect_bound.stderr new file mode 100644 index 00000000..37cb4969 --- /dev/null +++ b/src/gc-arena/tests/ui/bad_collect_bound.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `NotCollect: Collect` is not satisfied + --> $DIR/bad_collect_bound.rs:8:5 + | +8 | field: NotCollect + | ^^^^^^^^^^^^^^^^^ the trait `Collect` is not implemented for `NotCollect` + | + ::: $WORKSPACE/src/gc-arena/src/collect.rs + | + | Self: Sized, + | ----- required by this bound in `needs_trace` + +error[E0277]: the trait bound `NotCollect: Collect` is not satisfied + --> $DIR/bad_collect_bound.rs:8:5 + | +8 | field: NotCollect + | ^^^^^^^^^^^^^^^^^ the trait `Collect` is not implemented for `NotCollect` + | + = note: required by `trace`