mystor / synstructure

Utilities for dealing with substructures within syn macros

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ident sanitization causes name conflicts

dschoepe opened this issue · comments

Deduplicating consecutive underscores in sanitize_ident causes automatic derives to fail if one attempts to derive an implementation for a type Foo and _Foo. Here's a small example using abomonation_derive:

#[derive(Abomonation)]
pub struct Foo {
    x: String,
}

#[derive(Abomonation)]
pub struct _Foo {
    x: String,
}

Trying to compile this fails with the following error:

error[E0428]: the name `_DERIVE_abomonation_Abomonation_FOR_Foo` is defined multiple times
   --> dusty_example/src/main.rs:155:10
    |
149 | #[derive(Abomonation)]
    |          ----------- previous definition of the value `_DERIVE_abomonation_Abomonation_FOR_Foo` here
...
155 | #[derive(Abomonation)]
    |          ^^^^^^^^^^^ `_DERIVE_abomonation_Abomonation_FOR_Foo` redefined here
    |
    = note: `_DERIVE_abomonation_Abomonation_FOR_Foo` must be defined only once in the value namespace of this module

This would also be fixed by #41 allowing avoiding generating a custom _DERIVE_ name.

#43 has been merged, and published, which should allow avoiding this on rust >= 1.37 by using the new underscore_const method.

synstructure/src/lib.rs

Lines 1616 to 1660 in 864690b

/// Configure whether to use `const _` instead of a generated const name in
/// code generated by `gen_impl` and `bound_impl`.
///
/// This syntax is only supported by rust 1.37, and later versions.
///
/// Defaults to `false` for backwards compatibility reasons.
///
/// # Example
///
/// ```
/// # use synstructure::*;
/// let di: syn::DeriveInput = syn::parse_quote! {
/// struct MyStruct;
/// };
/// let mut s = Structure::new(&di);
///
/// assert_eq!(
/// s.underscore_const(true)
/// .gen_impl(quote! { gen impl Trait for @Self { } })
/// .to_string(),
/// quote! {
/// const _: () = {
/// impl Trait for MyStruct { }
/// };
/// }
/// .to_string()
/// );
///
/// assert_eq!(
/// s.underscore_const(false)
/// .gen_impl(quote! { gen impl Trait for @Self { } })
/// .to_string(),
/// quote! {
/// #[allow(non_upper_case_globals)]
/// const _DERIVE_Trait_FOR_MyStruct: () = {
/// impl Trait for MyStruct { }
/// };
/// }
/// .to_string()
/// );
/// ```
pub fn underscore_const(&mut self, enabled: bool) -> &mut Self {
self.underscore_const = enabled;
self
}

This will become the default behaviour in 0.13, if we end up making a breaking change.