struct NewtypeDefinition{
attrs: Vec<Attribute>,
vis: Visibility,
struct_token: Struct,
ident: Ident,
generics: Generics,
fields: Punctuated<Field, Comma>,
where_clause: Option<WhereClause>,
control_block: Option<Punctuated<ControlDef, Semi>>,
}
enum ControlDef{
FunctionDef(FunctionDefinition),
TraitDef(TraitDefinition),
}
enum FunctionDefinition{
Suppressed {
not: Token![!],
fn_token: Fn,
ident: Ident,
},
Automatic {
fn_token: Fn,
ident: Ident,
},
//not: Token![!],
//fn_token: Fn,
//ident: Ident,
// generics: Generics,
// paren_token: Paren,
// inputs: Punctuated<FnArg, Comma>,
// output: ReturnType,
// where_clause: Option<WhereClause>,
// control_block: Option<Punctuated<Item, Semi>>,
}
enum TraitDefinition{
Suppressed {
not: Token![!],
trait_token: Trait,
ident: Ident,
},
Automatic {
trait_token: Trait,
ident: Ident,
},
Manual {
trait_token: Trait,
ident: Ident,
// impl block
},
}
struct NewtypeDefinitions{
definitions: Punctuated<NewtypeDefinition, Semi>,
}
impl Parse for NewtypeDefinition {
fn parse(input: ParseStream) -> Result<Self> {
let fields;
let control_block;
Ok(
NewtypeDefinition {
attrs: input.call(Attribute::parse_outer)?,
vis: input.parse()?,
struct_token: input.parse()?,
ident: input.parse()?,
generics: input.parse()?,
fields: {parenthesized!(fields in input); fields.parse_terminated(Field::parse_unnamed, Comma)?},
where_clause: input.parse()?,
control_block: {parenthesized!(control_block in input); control_block.parse_terminated(Item::parse, Semi)?},
}
)
// let attributes = input.call(Attribute::parse_outer)?;
// let vis: Visibility = input.parse()?;
//
// input.parse::<Token![struct]>()?;
//
// let name = input.parse::<Ident>()?;
// let generics = input.parse::<syn::Generics>()?;
//
// let fields;
// parenthesized!(fields in input);
// let fields: Punctuated<Field, Token![,]> = fields.parse_terminated(Field::parse_unnamed, Token![,])?;
// //.parse_terminated(Field::parse_unnamed)?;
// //= input.call(syn::Field::parse_unnamed)?;
//
// let where_clause= input.parse::<syn::WhereClause>().ok();
//let fields;
//parenthesized!(fields in input);
//let fields: Punctuated<Field, Token![,]> = fields.parse_terminated(Field::parse_unnamed, Token![,])?;
// input.parse::<Token![;]>()?;
//
//
// Ok(
// NewtypeDefinition{
// //attributes,
// //vis,
// }
// )
// let fields = input.parse::<syn::Fields>()?;
// let attribute = input.parse::<syn::Attribute>();
// let lookahead = input.lookahead1();
//
//
// let attributes: Vec<syn::Attribute> = Vec::new();
//
//
// // parse attributes
// while lookahead.peek(Token![#]) {
//
// input.parse::<syn::Attribute>().map(|attr| attributes.push(attr));
//
// } //else
//if lookahead.peek(Token![enum]) {
// input.parse().map(Item::Enum)
// } else {
// Err(lookahead.error())
// }
// todo!()
}
}
#[proc_macro]
pub fn newtype(tt: TokenStream) -> TokenStream {
let ttt = tt.clone();
let newtype= parse_macro_input!(tt as NewtypeDefinition);
//let newtype= parse_macro_input!(tt as DeriveInput);
//let attributes = Vec::new();
//let ii= tt.into_iter();
//
//
//eprintln!("{newtype:#?}");
// eprintln!("{tt2:#?}");
// eprintln!("{tt}");
//"fn answer() -> u32 { 42 }".parse().unwrap()
//tt.into()
ttt //todo!()
}
// PLANNED: 'where' clauses
// // macro macro generation at toplevel
//
// /// Checks if one of the given patterns appears in a list, and returns either the `then` or
// /// `else` part.
// #[doc(hidden)]
// #[macro_export]
// macro_rules! contains {
// (dollar_sign ($d:tt) if ($(($($pattern:tt)*))+) in defs ($($list:tt)*) $(then ($($yes:tt)*))? $(else ($($no:tt)*))?) => (
// $crate::contains!(dollar_sign ($) if ($(($($pattern)*))+) in ($crate::defs_to_list($($list)*))
// $(then ($($yes)*))? $(else ($($no)*))?);
// );
//
// (dollar_sign ($d:tt) if ($(($($pattern:tt)*))+) in ($(($($list:tt)*))*) $(then ($($yes:tt)*))? $(else ($($no:tt)*))?) => (
// macro_rules! contains_intern {
// // generate one clause for each pattern
// $((@rec ($($pattern)*)$d(($_:tt))*) => (contains_intern!(@yes));)+
// // no match recursion step
// (@rec ($_:tt)$d(($tail:tt))*) => (contains_intern!(@rec $d(($tail))*));
//
// // end of recursion, nothing found
// (@rec) => ($($($no)*)?);
//
// // error handling
// (@rec $d($error:tt)*) => (compile_error!(stringify!(Error in newtype list < $d($error)* >)));
//
// // branch when something was found
// (@yes) => ($($($yes)*)?);
// }
// contains_intern!(@rec $(($($list)*))*);
// );
//
// // error handling, be nice and give a hint
// (dollar_sign ($d:tt) if () $($_:tt)*) => (compile_error!(stringify!(Syntax error: if needs a non empty list)));
//
// // entry point
// (if $($rest:tt)*) => (
// // need to pass $ because of https://github.com/rust-lang/rust/issues/35853
// $crate::contains!(dollar_sign ($) if $($rest)*);
// );
//
// // error handling
// (&($error:tt)*) => (compile_error!(stringify!(Syntax error in contains! macro < $d($error)* >)));
// }
//
// #[test]
// fn contains_macro() {
// contains!(if ((foo bar)) in () then (panic!()) else ());
// contains!(if ((foo)) in ((foo)(bar)) then (println!("ok")) else (panic!()));
// contains!(if ((foo)) in ((foo)(bar)(baz)) then (println!("ok")) else (panic!()));
// contains!(if ((bar)) in ((foo)(bar)(baz)) then (println!("ok")) else (panic!()));
// contains!(if ((baz)) in ((foo)(bar)(baz)) then (println!("ok")) else (panic!()));
// contains!(if ((barf)) in ((foo)(bar)(baz)) then (panic!()) else (println!("ok")));
// contains!(if ((barf)(bar)) in ((foo)(bar)(baz)) then (println!("ok")) else (panic!()));
// contains!(if ((foo)(bar)) in ((foo)(bar)(baz)) then (println!("ok")) else (panic!()));
//
// // then and else are optional
// contains!(if ((foo)) in ((foo)(bar)));
// contains!(if ((foo)) in ((foo)(bar)) then (println!("ok")));
// contains!(if ((barf)) in ((foo)(bar)(baz)) else (println!("ok")));
// }
//
// /// Extracts 'fn name', 'trait name' and the negations, return them as list
// /// usable with the `contains!()` macro.
// #[doc(hidden)]
// #[macro_export]
// macro_rules! defs_to_list {
// // matching all function defs
// (!fn $name:ident;$($tail:tt)*) => (
// //show!(!fn $name);
// (!fn $name)
// $crate::defs_to_list!($($tail)*)
// );
// ($pub:vis fn $name:ident$(<$($generics:tt),*>)?$(($($params:tt)*) $(-> $ret:ty)?)?; $($tail:tt)*) => (
// //show!(fn $name);
// (fn $name)
// $crate::defs_to_list!($($tail)*)
// );
// ($pub:vis fn $name:ident$(<$($generics:tt),*>)?$(($($params:tt)*) $(-> $ret:ty)?)?$block:block $($tail:tt)*) => (
// //show!(fn $name);
// (fn $name)
// $crate::defs_to_list!($($tail)*)
// );
// ($pub:vis const fn $name:ident$(<$($generics:tt),*>)?$(($($params:tt)*) $(-> $ret:ty)?)?; $($tail:tt)*) => (
// //show!(fn $name);
// (fn $name)
// $crate::defs_to_list!($($tail)*)
// );
// ($pub:vis const fn $name:ident$(<$($generics:tt),*>)?$(($($params:tt)*) $(-> $ret:ty)?)?$block:block $($tail:tt)*) => (
// //show!(fn $name);
// (fn $name)
// $crate::defs_to_list!($($tail)*)
// );
//
// // matching all trait defs
// (!trait $name:ident;$($tail:tt)*) => (
// //show!(!trait $name);
// (!trait $name)
// $crate::defs_to_list!($($tail)*)
// );
// (trait$(<$($generics1:tt),*>)? $name:ident$(<$($generics2:tt),*>)?;$($tail:tt)*) => (
// //show!(trait $name);
// (trait $name)
// $crate::defs_to_list!($($tail)*)
// );
// (trait$(<$($generics1:tt),*>)? $name:ident$(<$($generics2:tt),*>)?$block:block $($tail:tt)*) => (
// //show!(trait $name);
// (trait $name)
// $crate::defs_to_list!($($tail)*)
// );
//
// // end of recursion, excess semicolon or error
// () => ();
// (; $($tail:tt)*) => (
// $crate::defs_to_list!($($tail)*)
// );
// ($($error:tt)*) => (compile_error!(stringify!(Error in newtype "defs" block at < $($error)* > )));
// }
//
// // This works only when the '//show!(..' lines are uncommented and the real output is commented
// // #[test]
// // fn defs_to_list_test() {
// // defs_to_list! {
// // !fn baz;
// // fn foo;
// // fn bar {}
// // pub const fn pfn { 42 }
// // fn more();
// // fn more1(&self);
// // fn more2() -> i32;
// // fn more3() -> i32 {42}
// // fn generic<'a,T>(&self, t:T) -> U;
// // !trait Bar;
// // trait Foo;
// // trait Baz { fn baz(){} }
// // trait<'a, T> Baz<'a,T>;
// // trait<'a, T> Baz<'a,T> { fn baz(){} };;
// // };
// // }
// /// The newtype macro creates a struct with the given name and generates the boilerplate code
// /// that comes with the newtype idiom.
// ///
// /// # Syntax
// ///
// /// This gives a rough idea of the syntax used. For more details, see the below. Many parts
// /// are optional and can be left out. In simple words this is a usual newtype definition
// /// followed by a block of abbreviated function and trait definitions in curly braces.
// ///
// /// ```rust,ignore
// /// newtype!(
// /// // Simple newtype
// /// struct SimpleNewTypeName(WrappedType);
// ///
// /// // Complex newtype
// /// /// doc comment
// /// #[attributes]
// /// pub struct NewTypeName<'lifetimes, generics>(pub WrappedType, MarkerTypes) {
// /// // automatic trait implementation
// /// trait Trait;
// /// // explicit trait implementation
// /// trait Trait { fn traitfn(){} }
// /// // automatic function implementation on `impl NewTypeName { ...`
// /// const fn name(params) -> ReturnType;
// /// fn name(params) -> ReturnType;
// /// // explicit function implementation
// /// fn name(params) -> ReturnType { todo!() };
// /// TODO: method forwarding fn foo(&self,$(params)) -> DerefReturn; { self.0.foo($(params)) }
// /// // suppress predefined trait and function implementations
// /// !trait Trait;
// /// !fn name;
// /// }
// /// );
// /// ```
// ///
// /// # The newtype macro generates
// ///
// /// ## The struct
// ///
// /// The struct is generated as given. The newtype idiom is represented by a struct with only a
// /// single data member of the wrapped type. We expect this to be a tuple struct. This tuple
// /// can have additional zero length marker entries such as `PhantomData`. Lifetimes and
// /// generics can be used as usual. One can define any number of attributes before the actual
// /// struct definition. This includes rustdoc comments as these are just syntactic sugar for
// /// attributes. Both, the struct and the wrapped type can be declared `pub`. Newtype structs
// /// will always be `#[repr(transparent)]`, this ensures that one can't pass non ZST types as
// /// markers and that the memory layout always matches the wrapped type.
// // PLANNED: are there cases where we need to suppress this? -> #[repr(Rust)] or any other prevents this
// ///
// /// ## The structs `impl` block
// ///
// /// `newtype` generates an impl block for the struct, containing the functions below.
// /// When this is not enough one can add additional impl blocks after the newtype macro.
// ///
// /// ### `fn new(t: WrappedType) -> Self`
// ///
// /// The constructor for creating this struct. This function will be `pub` when the struct is `pub`.
// /// One can override this with a custom implementation eg. `const fn new(t: Into<T>) -> Self;`
// ///
// /// The override can have none or one parameter. When only the prototype is given then the
// /// code is generated automatically. In case of zero arguments a default constructed value is
// /// returned. When one argument is given then this will be used to construct the value via
// /// `.into()`. In case the implementation block is given the number of parameters are not
// /// limited.
// ///
// /// ### `fn take(s: Self) -> WrappedType`
// ///
// /// This associated function takes the value out of the newtype. This function will be `pub`
// /// when the struct is `pub`. The generation of this function can be suppressed with `!fn
// /// take;`.
// ///
// /// ### `fn get(&self) -> &WrappedType` and `fn get_mut(&mut self) -> &mut WrappedType`
// ///
// /// These methods are not automatically generated. To get these specify `fn get;` and `fn
// /// get_mut;`.
// ///
// /// ## Automatic Traits
// ///
// /// The following traits are by default implemented:
// ///
// /// * `AsRef<WrappedType>` and `AsMut<WrappedType>`
// /// * `Borrow<WrappedType>` and `BorrowMut<WrappedType>`
// /// * `From<WrappedType>`
// ///
// /// Either of these can be suppressed with specifying `!trait Trait;`.
// ///
// /// `Deref` and `DerefMut` are not implemented by default. This can be done by specifying `trait
// /// Deref;` or `trait DerefMut;`. They dereference to the wrapped type. When something else is
// /// desired then they can be explicitly defined.
// ///
// /// ## Manual Traits
// ///
// /// By writing `trait Trait { fn traitfn(){} }` one can implement any trait for the newtype.
// /// The `for NewType` part and lifetimes are inserted automatically when not specified.
// /// It is possible to implement traits outside of the newtype macro as well.
// #[macro_export]
// macro_rules! newtype {
// (
// $(
// $(#[$($attrs:meta),*])*
// $pub:vis struct
// $name:ident$(<$($generics:tt),*>)? (
// $pub_inner:vis
// $type:ty
// $(, $($markers:ident)::* $(<$($markers_generics:tt),*>)?)*
// )
// $({$($defs:tt)*})?
// );*
// ) => {
// $(
// #[repr(transparent)]
// $($(#[$attrs])*)*
// $pub struct $name$(<$($generics),*>)?($pub_inner $type $(, $($markers)::* $(<$($markers_generics),*>)? )*);
//
//
// //$crate::contains!{if ((fn new)(!fn new)) in ($crate::defs_to_list!($($defs)*))}
// $(
// //$crate::contains!{if ((fn new)(!fn new)) in ($crate::defs_to_list!($($defs),*))}
// $crate::contains!{if ((fn new)(!fn new)) in defs($($defs)*)}
// )?
//
// $($crate::defs_to_list!($($defs)*);)?
// // $crate::contains!{if ((fn new)(!fn new)) in ($crate::defs_to_list!($($defs)*)) then (
// // // impl$(<$($generics),*>)? $name$(<$($generics),*>)? {
// // // }
// // )}
//
//
// )*
// };
// }
// // since macros cant be defined in impl blocks or traits we need to do this here and expand right away
// macro_rules! newtype_impls {
// ($d:tt) => {
//
//
// impl$(<$($generics),*>)? $name$(<$($generics),*>)? {
// // PLANNED: needs explicit prototype or implementation
//
//
//
// // if () in () then (
// // ;
// //
// //
// //
// //
// // // $crate:newtype_fn!([$type $(, $($markers)::*)*] $pub fn new);
// // // $pub fn new(value: $type) -> Self {
// // // Self(value $(, $($markers)::* )*)
// // // }
// //
// // )
//
// /// Takes the value out of the newtype.
// // PLANNED: !fn take @ifnot explicit
// $pub fn take(value: Self) -> $type {
// value.0
// }
//
// // $pub fn new_old(value: $type) -> Self {
// // Self(value $(, $($markers)::* )*)
// // }
//
// // impl fns from $defs
//
// }
//
// };
// }
//
// // do the dollar_sign dance again
// newtype_impls!($);
// // PLANNED: !impl AsRef AsMut ... @ifnot explicit
// impl$d(<$d($generics),*>)? std::convert::AsRef<$type> for $name$d(<$d($generics),*>)? {
// fn as_ref(&self) -> &$type {
// &self.0
// }
// }
//
// impl$d(<$d($generics),*>)? std::convert::AsMut<$type> for $name$d(<$d($generics),*>)? {
// fn as_mut(&mut self) -> &mut $type {
// &mut self.0
// }
// }
//
// impl$d(<$d($generics),*>)? std::borrow::Borrow<$type> for $name$d(<$d($generics),*>)? {
// fn borrow(&self) -> &$type {
// &self.0
// }
// }
//
// impl$d(<$d($generics),*>)? std::borrow::BorrowMut<$type> for $name$d(<$d($generics),*>)? {
// fn borrow_mut(&mut self) -> &mut $type {
// &mut self.0
// }
// }
//
// // PLANNED: !impl From
// impl$d(<$d($generics),*>)? std::convert::From<$type> for $name$d(<$d($generics),*>)? {
// fn from(value: $type) -> Self {
// Self(value $d(, $d($markers)::* )*)
// }
// }
// //($crate::contains!{if ((fn new)) in ()}
//
//
//
// )*
// /// The function/method generators
// #[doc(hidden)]
// #[macro_export]
// macro_rules! newtype_fn {
// // new()
// ([$type:ty $(, $($markers:ident)::*)*] $pub:vis const fn new) => {
// $pub const fn new(value: $type) -> Self {
// Self(value $(, $($markers)::* )*)
// }
// };
// ([$type:ty $(, $($markers:ident)::*)*] $pub:vis fn new) => {
// $pub fn new(value: $type) -> Self {
// Self(value $(, $($markers)::* )*)
// }
// };
//
// // take()
//
// // get/get_mut
//
// // function forwarding
//
// // generic fn
// }
//
// #[doc(hidden)]
// #[macro_export]
// macro_rules! newtype_fn {
// (@fn ) => {};
// }
//
// #[doc(hidden)]
// #[macro_export]
// macro_rules! newtype_trait {
// (@fn ) => {};
// }
// macro_rules! test {
//
// // (@type_path $name:ident $(:: $path:ident)* $(<$($lifetimes:lifetime),* $(,$generics:ident)*>)?) => (
// // $name $(:: $path)*
// // );
// // (@type_path $name:ident $(:: $path:ident)* $(<$($lifetimes:lifetime),* $(,$generics:ident)*>)?) => (
// // $name $(:: $path)*
// // );
// //(@type_path $path:tt $(<$($lifetimes:lifetime),* $(,$generics:ident)*>)?) => (
// (@type_path $($path:ident)::* $(<$($lifetimes:lifetime),* $(,$generics:ident)*>)?) => (
//
// type $($path)::* = ();
// //type $path = ();
// );
//
// // ($($item:tt)*) => (
// // test!($(@type_path $item)*);
// // );
// }
//
// test! {
// // Foo
// @type_path Foo<'a, T>
// }
// [20:43] <danieldg> cehteh: like macro_rules contains_foo { () => false; (foo, $($list:ident),*) => true; ($one:ident, $($list:ident),*) => contains_foo!($($list),*); }
// PLANNED: get() -> T; get() -> &T
// PLANNED: set(T);set( &T)
// PLANNED: swap(T)-> T; swap(&T) -> T
// PLANNED: when Copy or Clone are defined as attrs, then we can rely on that
// // Trivial newtype
// newtype!(
// struct WrapedNumberA(i32);
// // struct WrapedNumberB(i32);
// );
//
//
// // Trivial newtype
// newtype!(
// #[derive(Debug)]
// #[repr(Rust)]
// /// A i32 wrapped in a newtype.
// struct WrapedNumberC(i32, pub f64)
// where i32: std::fmt::Debug
// // {
// // fn foo;
// // trait Bar;
// // !fn new;
// // // provide a `new` function that overrides the automatic implementation
// // pub const fn new() -> Self {Self(String::new())}
// //
// // // suppress the generation of the `take` function
// // !fn take;
// //
// // // generates a method `push_str` that forwards to `String::push_str()`
// // pub fn push_str(&self, s: &str);
// //
// // // implement a custom method
// // pub fn hello(&self) {
// // println!("Hello {}!", self.0);
// // }
// //
// // // implement a trait
// // trait Hello {
// // fn hello(&self) {
// // println!("Hello {}!", self.0);
// // }
// // }
// //
// // // suppress the automatic implementation of the `From` trait
// // !impl From;
// // }
// ;
// );
// Attribute macro syntax
// #[newtype]
// struct WrapedNumberD(i32);
// #[newtype(controlblock)]
// struct WrapedNumberD(i32);
// #[newtype{controlblock}]
// struct WrapedNumberD(i32);
// #[test]
// fn smoke() {
// let wn = WrapedNumber(42);
// println!("{}", wn.0);
// assert_eq!(wn.0, 42);
// // assert_eq!(WrapedNumber::take(wn), 42);
// }
// // With docs
// newtype!(
// /// This is a doc comment
// struct WithDoc(())
// );
//
// // With lifetime & attributes
// newtype!(
// #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
// pub struct Text<'a>(pub &'a str)
// );
//
// #[test]
// fn text() {
// let text = Text("Hello, world!");
// println!("{}", text.0);
// }
//
// newtype! {
// // With lifetime & generics
// pub struct ValueA<'a,T>(&'a T);
// // With generics
// pub struct ValueB<T>(T);
// // With Marker
// pub struct ValueC(String, std::marker::PhantomData<i32>);
// }
// // test autogenerated traits
// #[test]
// fn valueb() {
// let valueb = ValueB::new(42);
// assert_eq!(ValueB::take(valueb), 42);
// println!("{}", valueb.0);
// assert_eq!(valueb.0, 42);
// }
// macro_rules! impl_never_product_expand {
// ($($ty:ty),*) => {
// $(
// impl NeedsProductExpand for $ty {
// fn needs_product_expand(&self) -> bool {
// false
// }
// }
// )*
// };
// (true $($ty:ty),*) => {
// $(
// impl NeedsProductExpand for $ty {
// fn needs_product_expand(&self) -> bool {
// false
// }
// }
// )*
// };
// () => {};
// }
// impl_needs_product_expand!{syn::Generics}
// // The function/method generators
// #[doc(hidden)]
// #[macro_export]
// macro_rules! newtype_fn {
// // new()
// ([$type:ty $(, $($markers:ident)::*)*] $pub:vis const fn new) => {
// $pub const fn new(value: $type) -> Self {
// Self(value $(, $($markers)::* )*)
// }
// };
// ([$type:ty $(, $($markers:ident)::*)*] $pub:vis fn new) => {
// $pub fn new(value: $type) -> Self {
// Self(value $(, $($markers)::* )*)
// }
// };
//
// // take()
//
// // get/get_mut
//
// // function forwarding
//
// // generic fn
// }
//
//
// // macro_rules! test {
// //
// // // (@type_path $name:ident $(:: $path:ident)* $(<$($lifetimes:lifetime),* $(,$generics:ident)*>)?) => (
// // // $name $(:: $path)*
// // // );
// // // (@type_path $name:ident $(:: $path:ident)* $(<$($lifetimes:lifetime),* $(,$generics:ident)*>)?) => (
// // // $name $(:: $path)*
// // // );
// // //(@type_path $path:tt $(<$($lifetimes:lifetime),* $(,$generics:ident)*>)?) => (
// // (@type_path $($path:ident)::* $(<$($lifetimes:lifetime),* $(,$generics:ident)*>)?) => (
// //
// // type $($path)::* = ();
// // //type $path = ();
// // );
// //
// // // ($($item:tt)*) => (
// // // test!($(@type_path $item)*);
// // // );
// // }
// //
//
// /// Checks if one of the given patterns appears in a list, and returns either the `then` or
// /// `else` part.
// #[doc(hidden)]
// #[macro_export]
// macro_rules! contains {
// (dollar_sign ($d:tt) if ($(($($pattern:tt)*))+) in ($(($($list:tt)*))*) $(then ($($yes:tt)*))? $(else ($($no:tt)*))?) => (
// macro_rules! contains_intern {
// // generate one clause for each pattern
// $((@rec ($($pattern)*)$d(($_:tt))*) => (contains_intern!(@yes));)+
// // no match recursion step
// (@rec ($_:tt)$d(($tail:tt))*) => (contains_intern!(@rec $d(($tail))*));
//
// // end of recursion, nothing found
// (@rec) => ($($($no)*)?);
//
// // error handling
// (@rec $d($error:tt)*) => (compile_error!(stringify!(Error in newtype list < $d($error)* >)));
//
// // branch when something was found
// (@yes) => ($($($yes)*)?);
// }
// contains_intern!(@rec $(($($list)*))*);
// );
//
// // error handling, be nice and give a hint
// (dollar_sign ($d:tt) if () $($_:tt)*) => (compile_error!(stringify!(Syntax error: if needs a non empty list)));
//
// // entry point
// (if $($rest:tt)*) => (
// // need to pass $ because of https://github.com/rust-lang/rust/issues/35853
// $crate::contains!(dollar_sign ($) if $($rest)*);
// );
//
// // error handling
// (&($error:tt)*) => (compile_error!(stringify!(Syntax error in contains! macro < $d($error)* >)));
// }
//
// #[test]
// fn contains_macro() {
// contains!(if ((foo bar)) in () then () else ());
// contains!(if ((foo)) in ((foo)(bar)) then (println!("yes")) else (println!("no")));
// contains!(if ((foo)) in ((foo)(bar)(baz)) then (println!("yes")) else (println!("no")));
// contains!(if ((foo)) in ((foo)(bar)(baz)) then (println!("yes")) else (println!("no")));
// contains!(if ((bar)) in ((foo)(bar)(baz)) then (println!("yes")) else (println!("no")));
// contains!(if ((baz)) in ((foo)(bar)(baz)) then (println!("yes")) else (println!("no")));
// contains!(if ((barf)) in ((foo)(bar)(baz)) then (println!("yes")) else (println!("no")));
// contains!(if ((barf)(bar)) in ((foo)(bar)(baz)) then (println!("yes")) else (println!("no")));
// contains!(if ((foo)(bar)) in ((foo)(bar)(baz)) then (println!("yes")) else (println!("no")));
//
// contains!(if ((foo)) in ((foo)(bar)));
// contains!(if ((foo)) in ((foo)(bar)) then (println!("yes")));
// contains!(if ((barf)) in ((foo)(bar)(baz)) else (println!("no")));
// }
//
// /// Extracts 'fn name', 'trait name' and the negations, return them as list
// /// usable with the `contains!()` macro.
// #[doc(hidden)]
// #[macro_export]
// macro_rules! defs_to_list {
// // matching all function defs
// (!fn $name:ident;$($tail:tt)*) => (
// //show!(!fn $name);
// (!fn $name)
// $crate::defs_to_list!($($tail)*)
// );
// ($pub:vis fn $name:ident$(<$($generics:tt),*>)?$(($($params:tt)*) $(-> $ret:ty)?)?; $($tail:tt)*) => (
// //show!(fn $name);
// (fn $name)
// $crate::defs_to_list!($($tail)*)
// );
// ($pub:vis fn $name:ident$(<$($generics:tt),*>)?$(($($params:tt)*) $(-> $ret:ty)?)?$block:block $($tail:tt)*) => (
// //show!(fn $name);
// (fn $name)
// $crate::defs_to_list!($($tail)*)
// );
// ($pub:vis const fn $name:ident$(<$($generics:tt),*>)?$(($($params:tt)*) $(-> $ret:ty)?)?; $($tail:tt)*) => (
// //show!(fn $name);
// (fn $name)
// $crate::defs_to_list!($($tail)*)
// );
// ($pub:vis const fn $name:ident$(<$($generics:tt),*>)?$(($($params:tt)*) $(-> $ret:ty)?)?$block:block $($tail:tt)*) => (
// //show!(fn $name);
// (fn $name)
// $crate::defs_to_list!($($tail)*)
// );
//
// // matching all trait defs
// (!trait $name:ident;$($tail:tt)*) => (
// //show!(!trait $name);
// (!trait $name)
// $crate::defs_to_list!($($tail)*)
// );
// (trait$(<$($generics1:tt),*>)? $name:ident$(<$($generics2:tt),*>)?;$($tail:tt)*) => (
// //show!(trait $name);
// (trait $name)
// $crate::defs_to_list!($($tail)*)
// );
// (trait$(<$($generics1:tt),*>)? $name:ident$(<$($generics2:tt),*>)?$block:block $($tail:tt)*) => (
// //show!(trait $name);
// (trait $name)
// $crate::defs_to_list!($($tail)*)
// );
//
// // end of recursion, excess semicolon or error
// () => ();
// (; $($tail:tt)*) => (
// $crate::defs_to_list!($($tail)*)
// );
// ($($error:tt)*) => (compile_error!(stringify!(Error in newtype "defs" block at < $($error)* > )));
// }
//
// // This works only when the '//show!(..' lines are uncommented and the real output is commented
// // #[test]
// // fn defs_to_list_test() {
// // defs_to_list! {
// // !fn baz;
// // fn foo;
// // fn bar {}
// // pub const fn pfn { 42 }
// // fn more();
// // fn more1(&self);
// // fn more2() -> i32;
// // fn more3() -> i32 {42}
// // fn generic<'a,T>(&self, t:T) -> U;
// // !trait Bar;
// // trait Foo;
// // trait Baz { fn baz(){} }
// // trait<'a, T> Baz<'a,T>;
// // trait<'a, T> Baz<'a,T> { fn baz(){} };;
// // };
// // }