/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
- // force-host
- // no-prefer-dynamic
- // These are tests for syntax that is accepted by the Rust parser but
- // unconditionally rejected semantically after macro expansion. Attribute macros
- // are permitted to accept such syntax as long as they replace it with something
- // that makes sense to Rust.
- //
- // We also inspect some of the spans to verify the syntax is not triggering the
- // lossy string reparse hack (https://github.com/rust-lang/rust/issues/43081).
- #![crate_type = "proc-macro"]
- #![feature(proc_macro_span)]
- extern crate proc_macro;
- use proc_macro::{token_stream, Delimiter, TokenStream, TokenTree};
- use std::path::Component;
- // unsafe mod m {
- // pub unsafe mod inner;
- // }
- #[proc_macro_attribute]
- pub fn expect_unsafe_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
- let tokens = &mut input.into_iter();
- expect(tokens, "unsafe");
- expect(tokens, "mod");
- expect(tokens, "m");
- let tokens = &mut expect_brace(tokens);
- expect(tokens, "pub");
- expect(tokens, "unsafe");
- expect(tokens, "mod");
- let ident = expect(tokens, "inner");
- expect(tokens, ";");
- check_useful_span(ident, "unsafe-mod.rs");
- TokenStream::new()
- }
- // unsafe extern {
- // type T;
- // }
- #[proc_macro_attribute]
- pub fn expect_unsafe_foreign_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
- let tokens = &mut input.into_iter();
- expect(tokens, "unsafe");
- expect(tokens, "extern");
- let tokens = &mut expect_brace(tokens);
- expect(tokens, "type");
- let ident = expect(tokens, "T");
- expect(tokens, ";");
- check_useful_span(ident, "unsafe-foreign-mod.rs");
- TokenStream::new()
- }
- // unsafe extern "C++" {}
- #[proc_macro_attribute]
- pub fn expect_unsafe_extern_cpp_mod(_attrs: TokenStream, input: TokenStream) -> TokenStream {
- let tokens = &mut input.into_iter();
- expect(tokens, "unsafe");
- expect(tokens, "extern");
- let abi = expect(tokens, "\"C++\"");
- expect_brace(tokens);
- check_useful_span(abi, "unsafe-foreign-mod.rs");
- TokenStream::new()
- }
- fn expect(tokens: &mut token_stream::IntoIter, expected: &str) -> TokenTree {
- match tokens.next() {
- Some(token) if token.to_string() == expected => token,
- wrong => panic!("unexpected token: {:?}, expected `{}`", wrong, expected),
- }
- }
- fn expect_brace(tokens: &mut token_stream::IntoIter) -> token_stream::IntoIter {
- match tokens.next() {
- Some(TokenTree::Group(group)) if group.delimiter() == Delimiter::Brace => {
- group.stream().into_iter()
- }
- wrong => panic!("unexpected token: {:?}, expected `{{`", wrong),
- }
- }
- fn check_useful_span(token: TokenTree, expected_filename: &str) {
- let span = token.span();
- assert!(span.start().column < span.end().column);
- let source_path = span.source_file().path();
- let filename = source_path.components().last().unwrap();
- assert_eq!(filename, Component::Normal(expected_filename.as_ref()));
- }