From 276fae11ea999e946a48b2150e59438eb8a5e442 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sat, 23 Jan 2016 13:37:54 -0500 Subject: [PATCH 1/2] thorough follow-set tests --- src/test/compile-fail/macro-follow.rs | 122 +++++++++++++++++ src/test/run-pass/macro-follow.rs | 190 ++++++++++++++++++++++++++ 2 files changed, 312 insertions(+) create mode 100644 src/test/compile-fail/macro-follow.rs create mode 100644 src/test/run-pass/macro-follow.rs diff --git a/src/test/compile-fail/macro-follow.rs b/src/test/compile-fail/macro-follow.rs new file mode 100644 index 00000000000..35944bada4d --- /dev/null +++ b/src/test/compile-fail/macro-follow.rs @@ -0,0 +1,122 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// Check the macro follow sets (see corresponding rpass test). + +// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)} +macro_rules! follow_pat { + ($p:pat ()) => {}; //~WARN `$p:pat` is followed by `(` + ($p:pat []) => {}; //~WARN `$p:pat` is followed by `[` + ($p:pat {}) => {}; //~WARN `$p:pat` is followed by `{` + ($p:pat :) => {}; //~ERROR `$p:pat` is followed by `:` + ($p:pat >) => {}; //~ERROR `$p:pat` is followed by `>` + ($p:pat +) => {}; //~ERROR `$p:pat` is followed by `+` + ($p:pat ident) => {}; //~ERROR `$p:pat` is followed by `ident` + ($p:pat $p:pat) => {}; //~ERROR `$p:pat` is followed by `$p:pat` + ($p:pat $e:expr) => {}; //~ERROR `$p:pat` is followed by `$e:expr` + ($p:pat $t:ty) => {}; //~ERROR `$p:pat` is followed by `$t:ty` + ($p:pat $s:stmt) => {}; //~ERROR `$p:pat` is followed by `$s:stmt` + ($p:pat $p:path) => {}; //~ERROR `$p:pat` is followed by `$p:path` + ($p:pat $b:block) => {}; //~ERROR `$p:pat` is followed by `$b:block` + ($p:pat $i:ident) => {}; //~ERROR `$p:pat` is followed by `$i:ident` + ($p:pat $t:tt) => {}; //~ERROR `$p:pat` is followed by `$t:tt` + ($p:pat $i:item) => {}; //~ERROR `$p:pat` is followed by `$i:item` + ($p:pat $m:meta) => {}; //~ERROR `$p:pat` is followed by `$m:meta` +} +// FOLLOW(expr) = {FatArrow, Comma, Semicolon} +macro_rules! follow_expr { + ($e:expr ()) => {}; //~WARN `$e:expr` is followed by `(` + ($e:expr []) => {}; //~WARN `$e:expr` is followed by `[` + ($e:expr {}) => {}; //~WARN `$e:expr` is followed by `{` + ($e:expr =) => {}; //~ERROR `$e:expr` is followed by `=` + ($e:expr |) => {}; //~ERROR `$e:expr` is followed by `|` + ($e:expr :) => {}; //~ERROR `$e:expr` is followed by `:` + ($e:expr >) => {}; //~ERROR `$e:expr` is followed by `>` + ($e:expr +) => {}; //~ERROR `$e:expr` is followed by `+` + ($e:expr ident) => {}; //~ERROR `$e:expr` is followed by `ident` + ($e:expr if) => {}; //~ERROR `$e:expr` is followed by `if` + ($e:expr in) => {}; //~ERROR `$e:expr` is followed by `in` + ($e:expr $p:pat) => {}; //~ERROR `$e:expr` is followed by `$p:pat` + ($e:expr $e:expr) => {}; //~ERROR `$e:expr` is followed by `$e:expr` + ($e:expr $t:ty) => {}; //~ERROR `$e:expr` is followed by `$t:ty` + ($e:expr $s:stmt) => {}; //~ERROR `$e:expr` is followed by `$s:stmt` + ($e:expr $p:path) => {}; //~ERROR `$e:expr` is followed by `$p:path` + ($e:expr $b:block) => {}; //~ERROR `$e:expr` is followed by `$b:block` + ($e:expr $i:ident) => {}; //~ERROR `$e:expr` is followed by `$i:ident` + ($e:expr $t:tt) => {}; //~ERROR `$e:expr` is followed by `$t:tt` + ($e:expr $i:item) => {}; //~ERROR `$e:expr` is followed by `$i:item` + ($e:expr $m:meta) => {}; //~ERROR `$e:expr` is followed by `$m:meta` +} +// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or, +// Ident(as), Ident(where), OpenDelim(Bracket)} +macro_rules! follow_ty { + ($t:ty ()) => {}; //~WARN `$t:ty` is followed by `(` + ($t:ty []) => {}; // ok (RFC 1462) + ($t:ty +) => {}; //~ERROR `$t:ty` is followed by `+` + ($t:ty ident) => {}; //~ERROR `$t:ty` is followed by `ident` + ($t:ty if) => {}; //~ERROR `$t:ty` is followed by `if` + ($t:ty $p:pat) => {}; //~ERROR `$t:ty` is followed by `$p:pat` + ($t:ty $e:expr) => {}; //~ERROR `$t:ty` is followed by `$e:expr` + ($t:ty $t:ty) => {}; //~ERROR `$t:ty` is followed by `$t:ty` + ($t:ty $s:stmt) => {}; //~ERROR `$t:ty` is followed by `$s:stmt` + ($t:ty $p:path) => {}; //~ERROR `$t:ty` is followed by `$p:path` + ($t:ty $b:block) => {}; //~ERROR `$t:ty` is followed by `$b:block` + ($t:ty $i:ident) => {}; //~ERROR `$t:ty` is followed by `$i:ident` + ($t:ty $t:tt) => {}; //~ERROR `$t:ty` is followed by `$t:tt` + ($t:ty $i:item) => {}; //~ERROR `$t:ty` is followed by `$i:item` + ($t:ty $m:meta) => {}; //~ERROR `$t:ty` is followed by `$m:meta` +} +// FOLLOW(stmt) = FOLLOW(expr) +macro_rules! follow_stmt { + ($s:stmt ()) => {}; //~WARN `$s:stmt` is followed by `(` + ($s:stmt []) => {}; //~WARN `$s:stmt` is followed by `[` + ($s:stmt {}) => {}; //~WARN `$s:stmt` is followed by `{` + ($s:stmt =) => {}; //~ERROR `$s:stmt` is followed by `=` + ($s:stmt |) => {}; //~ERROR `$s:stmt` is followed by `|` + ($s:stmt :) => {}; //~ERROR `$s:stmt` is followed by `:` + ($s:stmt >) => {}; //~ERROR `$s:stmt` is followed by `>` + ($s:stmt +) => {}; //~ERROR `$s:stmt` is followed by `+` + ($s:stmt ident) => {}; //~ERROR `$s:stmt` is followed by `ident` + ($s:stmt if) => {}; //~ERROR `$s:stmt` is followed by `if` + ($s:stmt in) => {}; //~ERROR `$s:stmt` is followed by `in` + ($s:stmt $p:pat) => {}; //~ERROR `$s:stmt` is followed by `$p:pat` + ($s:stmt $e:expr) => {}; //~ERROR `$s:stmt` is followed by `$e:expr` + ($s:stmt $t:ty) => {}; //~ERROR `$s:stmt` is followed by `$t:ty` + ($s:stmt $s:stmt) => {}; //~ERROR `$s:stmt` is followed by `$s:stmt` + ($s:stmt $p:path) => {}; //~ERROR `$s:stmt` is followed by `$p:path` + ($s:stmt $b:block) => {}; //~ERROR `$s:stmt` is followed by `$b:block` + ($s:stmt $i:ident) => {}; //~ERROR `$s:stmt` is followed by `$i:ident` + ($s:stmt $t:tt) => {}; //~ERROR `$s:stmt` is followed by `$t:tt` + ($s:stmt $i:item) => {}; //~ERROR `$s:stmt` is followed by `$i:item` + ($s:stmt $m:meta) => {}; //~ERROR `$s:stmt` is followed by `$m:meta` +} +// FOLLOW(path) = FOLLOW(ty) +macro_rules! follow_path { + ($p:path ()) => {}; //~WARN `$p:path` is followed by `(` + ($p:path []) => {}; // ok (RFC 1462) + ($p:path +) => {}; //~ERROR `$p:path` is followed by `+` + ($p:path ident) => {}; //~ERROR `$p:path` is followed by `ident` + ($p:path if) => {}; //~ERROR `$p:path` is followed by `if` + ($p:path $p:pat) => {}; //~ERROR `$p:path` is followed by `$p:pat` + ($p:path $e:expr) => {}; //~ERROR `$p:path` is followed by `$e:expr` + ($p:path $t:ty) => {}; //~ERROR `$p:path` is followed by `$t:ty` + ($p:path $s:stmt) => {}; //~ERROR `$p:path` is followed by `$s:stmt` + ($p:path $p:path) => {}; //~ERROR `$p:path` is followed by `$p:path` + ($p:path $b:block) => {}; //~ERROR `$p:path` is followed by `$b:block` + ($p:path $i:ident) => {}; //~ERROR `$p:path` is followed by `$i:ident` + ($p:path $t:tt) => {}; //~ERROR `$p:path` is followed by `$t:tt` + ($p:path $i:item) => {}; //~ERROR `$p:path` is followed by `$i:item` + ($p:path $m:meta) => {}; //~ERROR `$p:path` is followed by `$m:meta` +} +// FOLLOW(block) = any token +// FOLLOW(ident) = any token + +fn main() {} + diff --git a/src/test/run-pass/macro-follow.rs b/src/test/run-pass/macro-follow.rs new file mode 100644 index 00000000000..ce6498f67f9 --- /dev/null +++ b/src/test/run-pass/macro-follow.rs @@ -0,0 +1,190 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check the macro follow sets (see corresponding cfail test). + +// FOLLOW(pat) = {FatArrow, Comma, Eq, Or, Ident(if), Ident(in)} +macro_rules! follow_pat { + ($p:pat =>) => {}; + ($p:pat ,) => {}; + ($p:pat =) => {}; + ($p:pat |) => {}; + ($p:pat if) => {}; + ($p:pat in) => {}; +} +// FOLLOW(expr) = {FatArrow, Comma, Semicolon} +macro_rules! follow_expr { + ($e:expr =>) => {}; + ($e:expr ,) => {}; + ($e:expr ;) => {}; +} +// FOLLOW(ty) = {OpenDelim(Brace), Comma, FatArrow, Colon, Eq, Gt, Semi, Or, +// Ident(as), Ident(where), OpenDelim(Bracket)} +macro_rules! follow_ty { + ($t:ty {}) => {}; + ($t:ty ,) => {}; + ($t:ty =>) => {}; + ($t:ty :) => {}; + ($t:ty =) => {}; + ($t:ty >) => {}; + ($t:ty ;) => {}; + ($t:ty |) => {}; + ($t:ty as) => {}; + ($t:ty where) => {}; + ($t:ty []) => {}; +} +// FOLLOW(stmt) = FOLLOW(expr) +macro_rules! follow_stmt { + ($s:stmt =>) => {}; + ($s:stmt ,) => {}; + ($s:stmt ;) => {}; +} +// FOLLOW(path) = FOLLOW(ty) +macro_rules! follow_path { + ($p:path {}) => {}; + ($p:path ,) => {}; + ($p:path =>) => {}; + ($p:path :) => {}; + ($p:path =) => {}; + ($p:path >) => {}; + ($p:path ;) => {}; + ($p:path |) => {}; + ($p:path as) => {}; + ($p:path where) => {}; + ($p:path []) => {}; +} +// FOLLOW(block) = any token +macro_rules! follow_block { + ($b:block ()) => {}; + ($b:block []) => {}; + ($b:block {}) => {}; + ($b:block ,) => {}; + ($b:block =>) => {}; + ($b:block :) => {}; + ($b:block =) => {}; + ($b:block >) => {}; + ($b:block ;) => {}; + ($b:block |) => {}; + ($b:block +) => {}; + ($b:block ident) => {}; + ($b:block $p:pat) => {}; + ($b:block $e:expr) => {}; + ($b:block $t:ty) => {}; + ($b:block $s:stmt) => {}; + ($b:block $p:path) => {}; + ($b:block $b:block) => {}; + ($b:block $i:ident) => {}; + ($b:block $t:tt) => {}; + ($b:block $i:item) => {}; + ($b:block $m:meta) => {}; +} +// FOLLOW(ident) = any token +macro_rules! follow_ident { + ($i:ident ()) => {}; + ($i:ident []) => {}; + ($i:ident {}) => {}; + ($i:ident ,) => {}; + ($i:ident =>) => {}; + ($i:ident :) => {}; + ($i:ident =) => {}; + ($i:ident >) => {}; + ($i:ident ;) => {}; + ($i:ident |) => {}; + ($i:ident +) => {}; + ($i:ident ident) => {}; + ($i:ident $p:pat) => {}; + ($i:ident $e:expr) => {}; + ($i:ident $t:ty) => {}; + ($i:ident $s:stmt) => {}; + ($i:ident $p:path) => {}; + ($i:ident $b:block) => {}; + ($i:ident $i:ident) => {}; + ($i:ident $t:tt) => {}; + ($i:ident $i:item) => {}; + ($i:ident $m:meta) => {}; +} +// FOLLOW(tt) = any token +macro_rules! follow_tt { + ($t:tt ()) => {}; + ($t:tt []) => {}; + ($t:tt {}) => {}; + ($t:tt ,) => {}; + ($t:tt =>) => {}; + ($t:tt :) => {}; + ($t:tt =) => {}; + ($t:tt >) => {}; + ($t:tt ;) => {}; + ($t:tt |) => {}; + ($t:tt +) => {}; + ($t:tt ident) => {}; + ($t:tt $p:pat) => {}; + ($t:tt $e:expr) => {}; + ($t:tt $t:ty) => {}; + ($t:tt $s:stmt) => {}; + ($t:tt $p:path) => {}; + ($t:tt $b:block) => {}; + ($t:tt $i:ident) => {}; + ($t:tt $t:tt) => {}; + ($t:tt $i:item) => {}; + ($t:tt $m:meta) => {}; +} +// FOLLOW(item) = any token +macro_rules! follow_item { + ($i:item ()) => {}; + ($i:item []) => {}; + ($i:item {}) => {}; + ($i:item ,) => {}; + ($i:item =>) => {}; + ($i:item :) => {}; + ($i:item =) => {}; + ($i:item >) => {}; + ($i:item ;) => {}; + ($i:item |) => {}; + ($i:item +) => {}; + ($i:item ident) => {}; + ($i:item $p:pat) => {}; + ($i:item $e:expr) => {}; + ($i:item $t:ty) => {}; + ($i:item $s:stmt) => {}; + ($i:item $p:path) => {}; + ($i:item $b:block) => {}; + ($i:item $i:ident) => {}; + ($i:item $t:tt) => {}; + ($i:item $i:item) => {}; + ($i:item $m:meta) => {}; +} +// FOLLOW(meta) = any token +macro_rules! follow_meta { + ($m:meta ()) => {}; + ($m:meta []) => {}; + ($m:meta {}) => {}; + ($m:meta ,) => {}; + ($m:meta =>) => {}; + ($m:meta :) => {}; + ($m:meta =) => {}; + ($m:meta >) => {}; + ($m:meta ;) => {}; + ($m:meta |) => {}; + ($m:meta +) => {}; + ($m:meta ident) => {}; + ($m:meta $p:pat) => {}; + ($m:meta $e:expr) => {}; + ($m:meta $t:ty) => {}; + ($m:meta $s:stmt) => {}; + ($m:meta $p:path) => {}; + ($m:meta $b:block) => {}; + ($m:meta $i:ident) => {}; + ($m:meta $t:tt) => {}; + ($m:meta $i:item) => {}; + ($m:meta $m:meta) => {}; +} + +fn main() {} + From e1e0de86ec7ae5c572560a39282b54b410b49f83 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Sat, 23 Jan 2016 13:38:18 -0500 Subject: [PATCH 2/2] add `[` to FOLLOW(ty) and FOLLOW(path) Following RFC 1462 (amending 550). Closes #31135. --- src/libsyntax/ext/tt/macro_rules.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 9f069cb17ed..bfd76db0359 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -1005,7 +1005,7 @@ fn is_in_follow(_: &ExtCtxt, tok: &Token, frag: &str) -> Result { }, "path" | "ty" => { match *tok { - OpenDelim(token::DelimToken::Brace) | + OpenDelim(token::DelimToken::Brace) | OpenDelim(token::DelimToken::Bracket) | Comma | FatArrow | Colon | Eq | Gt | Semi | BinOp(token::Or) => Ok(true), Ident(i, _) if (i.name.as_str() == "as" || i.name.as_str() == "where") => Ok(true),