#![recursion_limit = "4096"] use syn::Type; use tt_call::{parse_type, tt_call}; macro_rules! assert_type { ($($tokens:tt)*) => { tt_call! { macro = [{ parse_type }] input = [{ $($tokens)* @ }] ~~> assert_type_return! { expected = [{ $($tokens)* }] } } }; } macro_rules! assert_type_return { { expected = [{ $($expected:tt)* }] type = [{ $($actual:tt)* }] rest = [{ @ }] } => { check(stringify!($($expected)*), stringify!($($actual)*)); }; } fn check(expected: &str, actual: &str) { assert_eq!( syn::parse_str::(expected).unwrap(), syn::parse_str::(actual).unwrap(), ); } #[test] fn test_parse_type() { // Paths assert_type!(u8); assert_type!(std::collections::HashMap); assert_type!(::std::collections::HashMap); // Angle brackets assert_type!(Vec); assert_type!(::Associated); assert_type!(::Associated); assert_type!(>::Associated); assert_type!( as Trait>::Associated); assert_type!(Iterator); assert_type!(RefMut<'a, u8>); // Square brackets assert_type!([u8]); assert_type!([u8; 64]); // Pointers assert_type!(*const u8); assert_type!(*mut u8); // References assert_type!(&u8); assert_type!(&mut u8); assert_type!(&'a u8); assert_type!(&'a mut u8); // Functions assert_type!(fn()); assert_type!(fn(u8)); assert_type!(fn(u8)); assert_type!(fn(u8, u8)); assert_type!(fn(a: u8, b: u8)); assert_type!(fn() -> u8); // Tuples assert_type!(()); assert_type!((u8)); assert_type!((u8,)); assert_type!((u8, u8)); // Traits assert_type!(dyn Display); assert_type!(dyn Display + Send); assert_type!(impl Display); assert_type!(impl Display + Send); assert_type!(impl Fn() -> Box + 'static); // Type macros assert_type!(m!()); assert_type!(m![]); assert_type!(m! {}); assert_type!(::m!()); assert_type!(::m!(u8)); assert_type!(crate::m!(u8)); // Special punctuation assert_type!(!); assert_type!(_); } #[test] fn test_futures() { assert_type!( futures::MapErr< futures::Map< futures::sink::SendAll< futures::stream::SplitSink< futures::stream::AndThen< tokio_core::io::Framed< Client, ipc::LenDelimited, >, fn( tokio_core::io::EasyBuf, ) -> std::result::Result, std::result::Result, >, >, futures::stream::Map< futures::stream::SplitStream< futures::stream::AndThen< tokio_core::io::Framed< Client, ipc::LenDelimited, >, fn( tokio_core::io::EasyBuf, ) -> std::result::Result< protobuf::Message::Message, std::io::Error, >, std::result::Result, >, >, H, >, >, fn( ( futures::stream::SplitSink< futures::stream::AndThen< tokio_core::io::Framed< Client, ipc::LenDelimited, >, fn( tokio_core::io::EasyBuf, ) -> std::result::Result< protobuf::Message::Message, std::io::Error, >, std::result::Result, >, >, futures::stream::Map< futures::stream::SplitStream< futures::stream::AndThen< tokio_core::io::Framed< Client, ipc::LenDelimited, >, fn( tokio_core::io::EasyBuf, ) -> std::result::Result< protobuf::Message::Message, std::io::Error, >, std::result::Result, >, >, H, > ), ), >, EH, > ); }