/src/test/ui/proc-macro/auxiliary/macro-only-syntax.rs

https://gitlab.com/rust-lang/rust · Rust · 89 lines · 63 code · 10 blank · 16 comment · 6 complexity · d68d3efe4faca0d5a663c6a07f3b96cf MD5 · raw file

  1. // force-host
  2. // no-prefer-dynamic
  3. // These are tests for syntax that is accepted by the Rust parser but
  4. // unconditionally rejected semantically after macro expansion. Attribute macros
  5. // are permitted to accept such syntax as long as they replace it with something
  6. // that makes sense to Rust.
  7. //
  8. // We also inspect some of the spans to verify the syntax is not triggering the
  9. // lossy string reparse hack (https://github.com/rust-lang/rust/issues/43081).
  10. #![crate_type = "proc-macro"]
  11. #![feature(proc_macro_span)]
  12. extern crate proc_macro;
  13. use proc_macro::{token_stream, Delimiter, TokenStream, TokenTree};
  14. use std::path::Component;
  15. // unsafe mod m {
  16. // pub unsafe mod inner;
  17. // }
  18. #[proc_macro_attribute]
  19. pub fn expect_unsafe_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
  20. let tokens = &mut input.into_iter();
  21. expect(tokens, "unsafe");
  22. expect(tokens, "mod");
  23. expect(tokens, "m");
  24. let tokens = &mut expect_brace(tokens);
  25. expect(tokens, "pub");
  26. expect(tokens, "unsafe");
  27. expect(tokens, "mod");
  28. let ident = expect(tokens, "inner");
  29. expect(tokens, ";");
  30. check_useful_span(ident, "unsafe-mod.rs");
  31. TokenStream::new()
  32. }
  33. // unsafe extern {
  34. // type T;
  35. // }
  36. #[proc_macro_attribute]
  37. pub fn expect_unsafe_foreign_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
  38. let tokens = &mut input.into_iter();
  39. expect(tokens, "unsafe");
  40. expect(tokens, "extern");
  41. let tokens = &mut expect_brace(tokens);
  42. expect(tokens, "type");
  43. let ident = expect(tokens, "T");
  44. expect(tokens, ";");
  45. check_useful_span(ident, "unsafe-foreign-mod.rs");
  46. TokenStream::new()
  47. }
  48. // unsafe extern "C++" {}
  49. #[proc_macro_attribute]
  50. pub fn expect_unsafe_extern_cpp_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
  51. let tokens = &mut input.into_iter();
  52. expect(tokens, "unsafe");
  53. expect(tokens, "extern");
  54. let abi = expect(tokens, "\"C++\"");
  55. expect_brace(tokens);
  56. check_useful_span(abi, "unsafe-foreign-mod.rs");
  57. TokenStream::new()
  58. }
  59. fn expect(tokens: &mut token_stream::IntoIter, expected: &str) -> TokenTree {
  60. match tokens.next() {
  61. Some(token) if token.to_string() == expected => token,
  62. wrong => panic!("unexpected token: {:?}, expected `{}`", wrong, expected),
  63. }
  64. }
  65. fn expect_brace(tokens: &mut token_stream::IntoIter) -> token_stream::IntoIter {
  66. match tokens.next() {
  67. Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => {
  68. group.stream().into_iter()
  69. }
  70. wrong => panic!("unexpected token: {:?}, expected `{{`", wrong),
  71. }
  72. }
  73. fn check_useful_span(token: TokenTree, expected_filename: &str) {
  74. let span = token.span();
  75. assert!(span.start().column < span.end().column);
  76. let source_path = span.source_file().path();
  77. let filename = source_path.components().last().unwrap();
  78. assert_eq!(filename, Component::Normal(expected_filename.as_ref()));
  79. }