#![feature(decl_macro)] #[derive(PartialEq, Eq, Debug)] pub enum Method { DefaultMacroCtxt, DefaultRootCtxt, OverrideMacroCtxt, OverrideRootCtxt, } #[rustfmt::skip] macro x($macro_name:ident, $macro2_name:ident, $trait_name:ident, $method_name:ident) { pub trait $trait_name { fn method(&self) -> Method { Method::DefaultMacroCtxt } fn $method_name(&self) -> Method { Method::DefaultRootCtxt } } impl $trait_name for () {} impl $trait_name for bool { fn method(&self) -> Method { Method::OverrideMacroCtxt } fn $method_name(&self) -> Method { Method::OverrideRootCtxt } } #[macro_export] macro_rules! $macro_name { (check_resolutions) => { assert_eq!(().method(), Method::DefaultMacroCtxt); assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt); assert_eq!(().$method_name(), Method::DefaultRootCtxt); assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt); assert_eq!(false.method(), Method::OverrideMacroCtxt); assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt); assert_eq!(false.$method_name(), Method::OverrideRootCtxt); assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt); assert_eq!('a'.method(), Method::DefaultMacroCtxt); assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt); assert_eq!('a'.$method_name(), Method::DefaultRootCtxt); assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt); assert_eq!(1i32.method(), Method::OverrideMacroCtxt); assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt); assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt); assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt); assert_eq!(1i64.method(), Method::OverrideMacroCtxt); assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt); assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt); assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt); }; (assert_no_override $v:expr) => { assert_eq!($v.method(), Method::DefaultMacroCtxt); assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt); assert_eq!($v.$method_name(), Method::DefaultRootCtxt); assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt); }; (assert_override $v:expr) => { assert_eq!($v.method(), Method::OverrideMacroCtxt); assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt); assert_eq!($v.$method_name(), Method::OverrideRootCtxt); assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt); }; (impl for $t:ty) => { impl $trait_name for $t { fn method(&self) -> Method { Method::OverrideMacroCtxt } fn $method_name(&self) -> Method { Method::OverrideRootCtxt } } }; } pub macro $macro2_name { (check_resolutions) => { assert_eq!(().method(), Method::DefaultMacroCtxt); assert_eq!($trait_name::method(&()), Method::DefaultMacroCtxt); assert_eq!(().$method_name(), Method::DefaultRootCtxt); assert_eq!($trait_name::$method_name(&()), Method::DefaultRootCtxt); assert_eq!(false.method(), Method::OverrideMacroCtxt); assert_eq!($trait_name::method(&false), Method::OverrideMacroCtxt); assert_eq!(false.$method_name(), Method::OverrideRootCtxt); assert_eq!($trait_name::$method_name(&false), Method::OverrideRootCtxt); assert_eq!('a'.method(), Method::DefaultMacroCtxt); assert_eq!($trait_name::method(&'a'), Method::DefaultMacroCtxt); assert_eq!('a'.$method_name(), Method::DefaultRootCtxt); assert_eq!($trait_name::$method_name(&'a'), Method::DefaultRootCtxt); assert_eq!(1i32.method(), Method::OverrideMacroCtxt); assert_eq!($trait_name::method(&1i32), Method::OverrideMacroCtxt); assert_eq!(1i32.$method_name(), Method::OverrideRootCtxt); assert_eq!($trait_name::$method_name(&1i32), Method::OverrideRootCtxt); assert_eq!(1i64.method(), Method::OverrideMacroCtxt); assert_eq!($trait_name::method(&1i64), Method::OverrideMacroCtxt); assert_eq!(1i64.$method_name(), Method::OverrideRootCtxt); assert_eq!($trait_name::$method_name(&1i64), Method::OverrideRootCtxt); }, (assert_no_override $v:expr) => { assert_eq!($v.method(), Method::DefaultMacroCtxt); assert_eq!($trait_name::method(&$v), Method::DefaultMacroCtxt); assert_eq!($v.$method_name(), Method::DefaultRootCtxt); assert_eq!($trait_name::$method_name(&$v), Method::DefaultRootCtxt); }, (assert_override $v:expr) => { assert_eq!($v.method(), Method::OverrideMacroCtxt); assert_eq!($trait_name::method(&$v), Method::OverrideMacroCtxt); assert_eq!($v.$method_name(), Method::OverrideRootCtxt); assert_eq!($trait_name::$method_name(&$v), Method::OverrideRootCtxt); }, (impl for $t:ty) => { impl $trait_name for $t { fn method(&self) -> Method { Method::OverrideMacroCtxt } fn $method_name(&self) -> Method { Method::OverrideRootCtxt } } } } } x!(test_trait, test_trait2, MyTrait, method); impl MyTrait for char {} test_trait!(impl for i32); test_trait2!(impl for i64); pub fn check_crate_local() { test_trait!(check_resolutions); test_trait2!(check_resolutions); } // Check that any comparison of idents at monomorphization time is correct pub fn check_crate_local_generic(t: T, u: U) { test_trait!(check_resolutions); test_trait2!(check_resolutions); test_trait!(assert_no_override t); test_trait2!(assert_no_override t); test_trait!(assert_override u); test_trait2!(assert_override u); }