You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

lib.rs 13KB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. //! code examples from "Productive Rust: Implementing Traits with Macros"
  2. //!
  3. //! # Examples
  4. //!
  5. //! ```compile_fail
  6. //! macro_rules! ah_ah_ah_didnt_say_the_magic_word {
  7. //! ($x:ident) => {
  8. //! let x_mut_1 = &mut $x;
  9. //! let x_mut_2 = &mut $x;
  10. //! *x_mut_1 += 1i32;
  11. //! }
  12. //! }
  13. //! let mut x: i32 = 0;
  14. //! ah_ah_ah_didnt_say_the_magic_word!(x);
  15. //! ```
  16. //!
  17. //! generic `min` won't compile:
  18. //!
  19. //!
  20. //! ```compile_fail
  21. //! fn min<T>(a: T, b: T) -> T {
  22. //! if a < b { a } else { b }
  23. //! }
  24. //! ```
  25. //!
  26. //! you can't add an i32 with a HashMap
  27. //!
  28. //!
  29. //! ```compile_fail
  30. //! macro_rules! add_one { ($x:ident) => { $x + 1i32 } }
  31. //! let b: std::collections::HashMap<String, u32> = Default::default();
  32. //! add_one!(b);
  33. //! ```
  34. //!
  35. //! you can't match a numeric literal against an $ident
  36. //!
  37. //!
  38. //! ```compile_fail
  39. //! macro_rules! add_one { ($x:ident) => { $x + 1i32 } }
  40. //! add_one(42i32);
  41. //! ```
  42. //!
  43. //! you can't generate a dynamic name with an $expr
  44. //!
  45. //!
  46. //! ```compile_fail
  47. //! macro_rules! make_adder_fn {
  48. //! ($n:expr) => {
  49. //! fn add_$n(rhs: i32) -> i32 {
  50. //! $n + rhs
  51. //! }
  52. //! }
  53. //! }
  54. //! make_adder_fn!(42);
  55. //! ```
  56. //!
  57. //! you can't match a $ty to create a struct
  58. //!
  59. //!
  60. //! ```compile_fail
  61. //! // ty can't be used to create a type, only to refer to one
  62. //! macro_rules! make_struct {
  63. //! ($t:ty, $x:ty, $y:ty) => {
  64. //! struct $t {
  65. //! pub x: f64,
  66. //! pub y: f64,
  67. //! }
  68. //! }
  69. //! }
  70. //! make_struct!(Point);
  71. //! ```
  72. //!
  73. //! code order example - with d present, can't compile
  74. //!
  75. //! ```compile_fail
  76. //! fn a() -> i32 { b() } // this is ok, even though `b` is below
  77. //!
  78. //! const B: i32 = b(); // also ok, even though `b` is below
  79. //!
  80. //! const fn b() -> i32 { 42 }
  81. //!
  82. //! d!(); // not ok
  83. //!
  84. //! macro_rules! d {
  85. //! () => {
  86. //! fn spooky_numbers() -> [usize; 6] {
  87. //! [4, 8, 15, 16, 23, 42]
  88. //! }
  89. //! }
  90. //! }
  91. //! ```
  92. #![allow(unused)]
  93. pub mod case_study;
  94. #[allow(unused)]
  95. #[cfg(test)]
  96. mod tests {
  97. #[test]
  98. fn a_bunch_of_print_lns_showing_var_args() {
  99. println!();
  100. println!("{}", 1);
  101. println!("{} {}", 1, 2);
  102. println!("{} {} {}", 1, 2, 3);
  103. }
  104. #[test]
  105. fn shows_vec_macro_and_its_equivalent() {
  106. let xs: Vec<i32> = vec![1, 2, 3];
  107. let ys: Vec<i32> = {
  108. let mut out = Vec::with_capacity(3);
  109. out.push(1);
  110. out.push(2);
  111. out.push(3);
  112. out
  113. };
  114. assert_eq!(xs, ys);
  115. }
  116. #[test]
  117. fn macro_that_if_used_would_generate_illegal_code_is_itself_not_illegal() {
  118. macro_rules! ah_ah_ah_didnt_say_the_magic_word {
  119. ($x:ident) => {
  120. let x_mut_1 = &mut $x;
  121. let x_mut_2 = &mut $x;
  122. *x_mut_1 += 1i32;
  123. }
  124. }
  125. }
  126. #[test]
  127. fn generic_min_macro_compiles_and_works() {
  128. macro_rules! min {
  129. ($a:expr, $b:expr) => {
  130. if $a < $b { $a } else { $b }
  131. }
  132. }
  133. let a: usize = 1;
  134. let b: usize = 2;
  135. assert_eq!(min!(a, b), 1);
  136. let c = f64::INFINITY;
  137. let d = f64::NEG_INFINITY;
  138. assert_eq!(min!(c, d), f64::NEG_INFINITY);
  139. }
  140. #[test]
  141. fn min_with_partial_ord_will_compile_thats_all_it_needs() {
  142. fn min_that_compiles<T: PartialOrd>(a: T, b: T) -> T {
  143. if a < b { a } else { b }
  144. }
  145. let a: usize = 1;
  146. let b: usize = 2;
  147. assert_eq!(min_that_compiles(a, b), 1);
  148. }
  149. #[test]
  150. fn generated_type_errors_the_example_of_something_that_works() {
  151. macro_rules! add_one {
  152. ($x:ident) => {
  153. $x + 1i32
  154. }
  155. }
  156. let a: i32 = 42;
  157. assert_eq!(add_one!(a), 43); // Ok: expands to i32 + i32
  158. }
  159. #[test]
  160. fn little_book_example_1_does_it_compile() {
  161. macro_rules! abacus {
  162. ((- $($moves:tt)*) -> (+ $($count:tt)*)) => {
  163. abacus!(($($moves)*) -> ($($count)*))
  164. };
  165. ((- $($moves:tt)*) -> ($($count:tt)*)) => {
  166. abacus!(($($moves)*) -> (- $($count)*))
  167. };
  168. ((+ $($moves:tt)*) -> (- $($count:tt)*)) => {
  169. abacus!(($($moves)*) -> ($($count)*))
  170. };
  171. ((+ $($moves:tt)*) -> ($($count:tt)*)) => {
  172. abacus!(($($moves)*) -> (+ $($count)*))
  173. };
  174. // Check if the final result is zero.
  175. (() -> ()) => { true };
  176. (() -> ($($count:tt)+)) => { false };
  177. }
  178. // this one never finishes
  179. //macro_rules! abacus2 {
  180. // (-) => {-1};
  181. // (+) => {1};
  182. // ($($moves:tt)*) => {
  183. // 0 $(+ abacus2!($moves))*
  184. // }
  185. //}
  186. let equals_zero = abacus!((++-+-+++--++---++----+) -> ());
  187. assert_eq!(equals_zero, true);
  188. //let equals_zero = abacus2!((++-+-+++--++---++----+) -> ());
  189. //assert_eq!(equals_zero, true);
  190. }
  191. #[test]
  192. fn little_book_example_2_does_it_compile() {
  193. macro_rules! parse_unitary_variants {
  194. (@as_expr $e:expr) => {$e};
  195. (@as_item $($i:item)+) => {$($i)+};
  196. // Exit rules.
  197. (
  198. @collect_unitary_variants ($callback:ident ( $($args:tt)* )),
  199. ($(,)*) -> ($($var_names:ident,)*)
  200. ) => {
  201. parse_unitary_variants! {
  202. @as_expr
  203. $callback!{ $($args)* ($($var_names),*) }
  204. }
  205. };
  206. (
  207. @collect_unitary_variants ($callback:ident { $($args:tt)* }),
  208. ($(,)*) -> ($($var_names:ident,)*)
  209. ) => {
  210. parse_unitary_variants! {
  211. @as_item
  212. $callback!{ $($args)* ($($var_names),*) }
  213. }
  214. };
  215. // Consume an attribute.
  216. (
  217. @collect_unitary_variants $fixed:tt,
  218. (#[$_attr:meta] $($tail:tt)*) -> ($($var_names:tt)*)
  219. ) => {
  220. parse_unitary_variants! {
  221. @collect_unitary_variants $fixed,
  222. ($($tail)*) -> ($($var_names)*)
  223. }
  224. };
  225. // Handle a variant, optionally with an with initialiser.
  226. (
  227. @collect_unitary_variants $fixed:tt,
  228. ($var:ident $(= $_val:expr)*, $($tail:tt)*) -> ($($var_names:tt)*)
  229. ) => {
  230. parse_unitary_variants! {
  231. @collect_unitary_variants $fixed,
  232. ($($tail)*) -> ($($var_names)* $var,)
  233. }
  234. };
  235. // Abort on variant with a payload.
  236. (
  237. @collect_unitary_variants $fixed:tt,
  238. ($var:ident $_struct:tt, $($tail:tt)*) -> ($($var_names:tt)*)
  239. ) => {
  240. const _error: () = "cannot parse unitary variants from enum with non-unitary variants";
  241. };
  242. // Entry rule.
  243. (enum $name:ident {$($body:tt)*} => $callback:ident $arg:tt) => {
  244. parse_unitary_variants! {
  245. @collect_unitary_variants
  246. ($callback $arg), ($($body)*,) -> ()
  247. }
  248. };
  249. }
  250. /*
  251. not sure how to invoke this one
  252. let mut variants: Vec<&'static str> = Vec::new();
  253. macro_rules! get_unitary_variant_str {
  254. {() ($($var_names),*) } => { $( variants.push(stringify!($variant)); )* }
  255. }
  256. parse_unitary_variants!(
  257. enum Abcs {
  258. A,
  259. B,
  260. C,
  261. D,
  262. E
  263. } => get_unitary_variant_str ()
  264. );
  265. */
  266. }
  267. #[test]
  268. fn tt_muncher_does_it_compile() {
  269. macro_rules! mixed_rules {
  270. () => {};
  271. (trace $name:ident; $($tail:tt)*) => {
  272. {
  273. println!(concat!(stringify!($name), " = {:?}"), $name);
  274. mixed_rules!($($tail)*);
  275. }
  276. };
  277. (trace $name:ident = $init:expr; $($tail:tt)*) => {
  278. {
  279. let $name = $init;
  280. println!(concat!(stringify!($name), " = {:?}"), $name);
  281. mixed_rules!($($tail)*);
  282. }
  283. };
  284. }
  285. mixed_rules!(trace x = 1;);
  286. }
  287. use std::fmt::Display;
  288. fn i_need_display_not_debug<T: Display>(x: T) -> String {
  289. format!("{}", x)
  290. }
  291. #[test]
  292. fn debug_display_macro_actually_works() {
  293. #[derive(Debug)]
  294. struct Point {
  295. pub x: f64,
  296. pub y: f64,
  297. }
  298. macro_rules! debug_display {
  299. ($t:ident) => {
  300. impl std::fmt::Display for $t {
  301. fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
  302. write!(f, "{:?}", self)
  303. }
  304. }
  305. }
  306. }
  307. debug_display!(Point); // poof! it implements Display
  308. let p = Point { x: 1.234, y: 2.345 };
  309. i_need_display_not_debug(p);
  310. }
  311. // did not end up using this
  312. #[test]
  313. fn example_for_why_you_should_use_fully_qualified_names() {
  314. pub struct A;
  315. pub trait Devious {
  316. fn abc(&self) -> isize { 42 }
  317. fn xyz(&self) -> isize { 42 }
  318. }
  319. impl Devious for A {}
  320. let a = A;
  321. macro_rules! didnt_see_it_coming {
  322. { $x:ident ;; } => {
  323. <A as Devious>::xyz(&$x)
  324. };
  325. { $x:ident <-> } => {
  326. <A as Devious>::abc(&$x)
  327. }
  328. }
  329. //let c = <A as ::tests::example_for_why_you_should_use_fully_qualified_names::Devious>::abc(&a);
  330. //macro_rules! you_gotta_be_wiser {
  331. // { [[ $x:ident ]] } => {
  332. // <A as ::tests::example_for_why_you_should_use_fully_qualified_names::Devious>::abc(&$x)
  333. // }
  334. // //{ [[ $x:ident ]] } => {
  335. // // <A as crate::tests::example_for_why_you_should_use_fully_qualified_names::Devious>::abc(&$x)
  336. // //};
  337. // //{ -^-^- $x:ident -^-^- } => {{
  338. // // // invoking the version that's inside `the_upside_down`
  339. // // use crate::tests::example_for_why_you_should_use_fully_qualified_names::the_upside_down::Devious as OtherDevious;
  340. // // <A as crate::tests::example_for_why_you_should_use_fully_qualified_names::the_upside_down::OtherDevious>::xyz(&$x)
  341. // //}};
  342. //}
  343. assert_eq!(didnt_see_it_coming!{ a <-> }, 42);
  344. //assert_eq!(you_gotta_be_wiser!{ [[ a ]] }, 42);
  345. //assert_eq!(you_gotta_be_wiser!{ -^-^- a -^-^- }, -42);
  346. /// muhaha
  347. fn the_upside_down(a: &A) -> isize {
  348. /// we have our own 'Devious' down here...
  349. pub trait Devious {
  350. fn abc(&self) -> isize { -42 }
  351. fn xyz(&self) -> isize { -42 }
  352. }
  353. impl Devious for A {}
  354. didnt_see_it_coming!{ a ;; }
  355. }
  356. assert_eq!(the_upside_down(&a), -42);
  357. }
  358. #[test]
  359. fn make_adder_with_supplied_name_working_example() {
  360. macro_rules! make_adder_fn {
  361. ($f:ident, $n:expr) => {
  362. fn $f(rhs: i32) -> i32 {
  363. $n + rhs
  364. }
  365. }
  366. }
  367. make_adder_fn!(add_42, 42);
  368. assert_eq!(add_42(0), 42);
  369. assert_eq!(add_42(42), 84);
  370. }
  371. #[test]
  372. fn ident_can_be_used_to_create_a_struct() {
  373. macro_rules! make_struct {
  374. ($t:ident) => {
  375. struct $t {
  376. pub x: f64,
  377. pub y: f64,
  378. }
  379. }
  380. }
  381. make_struct!(Point);
  382. }
  383. #[test]
  384. fn std_u32_exmple_works_with_macro_that_has_same_sig_as_uint_impl() {
  385. macro_rules! uint_impl_lookalike {
  386. ($SelfT:ty, $ActualT:ty, $BITS:expr, $MaxV:expr, $Feature:expr, $EndFeature:expr,
  387. $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr,
  388. $reversed:expr, $le_bytes:expr, $be_bytes:expr,
  389. $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => {
  390. assert!(true);
  391. }
  392. }
  393. uint_impl_lookalike! { u32, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678",
  394. "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
  395. }
  396. #[test]
  397. fn code_order_can_matter_everything_compiles_except_d() {
  398. fn a() -> i32 { b() } // this is ok, even though `b` is below
  399. const B: i32 = b(); // also ok, even though `b` is below
  400. const fn b() -> i32 { 42 }
  401. //d!(); // not ok
  402. macro_rules! d {
  403. () => {
  404. fn spooky_numbers() -> [usize; 6] {
  405. [4, 8, 15, 16, 23, 42]
  406. }
  407. }
  408. }
  409. }
  410. #[test]
  411. fn optionally_public_event_attr_can_be_used_from_here() {
  412. let active = crate::case_study::Active::default();
  413. let id = active.id();
  414. }
  415. }