/src/test/ui/proc-macro/auxiliary/expand-expr.rs

https://gitlab.com/rust-lang/rust · Rust · 80 lines · 59 code · 12 blank · 9 comment · 5 complexity · 4a0bc799638c88027efd514d726863c6 MD5 · raw file

  1. // force-host
  2. // no-prefer-dynamic
  3. #![crate_type = "proc-macro"]
  4. #![deny(warnings)]
  5. #![feature(proc_macro_expand, proc_macro_span)]
  6. extern crate proc_macro;
  7. use proc_macro::*;
  8. use std::str::FromStr;
  9. #[proc_macro]
  10. pub fn expand_expr_is(input: TokenStream) -> TokenStream {
  11. let mut iter = input.into_iter();
  12. let mut expected_tts = Vec::new();
  13. loop {
  14. match iter.next() {
  15. Some(TokenTree::Punct(ref p)) if p.as_char() == ',' => break,
  16. Some(tt) => expected_tts.push(tt),
  17. None => panic!("expected comma"),
  18. }
  19. }
  20. let expected = expected_tts.into_iter().collect::<TokenStream>();
  21. let expanded = iter.collect::<TokenStream>().expand_expr().expect("expand_expr failed");
  22. assert!(
  23. expected.to_string() == expanded.to_string(),
  24. "assert failed\nexpected: `{}`\nexpanded: `{}`",
  25. expected.to_string(),
  26. expanded.to_string()
  27. );
  28. TokenStream::new()
  29. }
  30. #[proc_macro]
  31. pub fn expand_expr_fail(input: TokenStream) -> TokenStream {
  32. match input.expand_expr() {
  33. Ok(ts) => panic!("expand_expr unexpectedly succeeded: `{}`", ts),
  34. Err(_) => TokenStream::new(),
  35. }
  36. }
  37. #[proc_macro]
  38. pub fn check_expand_expr_file(ts: TokenStream) -> TokenStream {
  39. // Check that the passed in `file!()` invocation and a parsed `file!`
  40. // invocation expand to the same literal.
  41. let input_t = ts.expand_expr().expect("expand_expr failed on macro input").to_string();
  42. let parse_t = TokenStream::from_str("file!{}")
  43. .unwrap()
  44. .expand_expr()
  45. .expect("expand_expr failed on internal macro")
  46. .to_string();
  47. assert_eq!(input_t, parse_t);
  48. // Check that the literal matches `Span::call_site().source_file().path()`
  49. let expect_t =
  50. Literal::string(&Span::call_site().source_file().path().to_string_lossy()).to_string();
  51. assert_eq!(input_t, expect_t);
  52. TokenStream::new()
  53. }
  54. #[proc_macro]
  55. pub fn recursive_expand(_: TokenStream) -> TokenStream {
  56. // Recursively call until we hit the recursion limit and get an error.
  57. //
  58. // NOTE: This doesn't panic if expansion fails because that'll cause a very
  59. // large number of errors to fill the output.
  60. TokenStream::from_str("recursive_expand!{}")
  61. .unwrap()
  62. .expand_expr()
  63. .unwrap_or(std::iter::once(TokenTree::Literal(Literal::u32_suffixed(0))).collect())
  64. }
  65. #[proc_macro]
  66. pub fn echo_pm(input: TokenStream) -> TokenStream {
  67. input
  68. }