Change:
E.g. in a vec is created, only to be thrown away if the macro actually works out. I think we can just turn most places into an early return in the happy path and then only allocate in the error path. Do not work on this issue before is merged. Also, hasn't had its docs updated to reflect the source changes.
Are there any reasons to not use constant/static slices and convert them to vecs on demand? Or maybe even convert to something like so there's no need to allocate vecs (In all cases) anymore?
That's a great idea! I haven't checked whether it'll work everywhere, but I think it should.

Discussion:
continue 'each_last; } IsInFollow::Yes => {} <del> IsInFollow::No(ref possible) => { </del> <ins> IsInFollow::No(possible) => { </ins> let may_be = if last.tokens.len() == 1 && suffix_first.tokens.len() == 1 {

format!("not allowed after `{}` fragments", frag_spec), ); let msg = "allowed there are: "; <del> match &possible[..] { </del> <ins> match possible { </ins> &[] => {} &[t] => { err.note(&format!(

enum IsInFollow { Yes, <del> No(Vec<&'static str>), </del> <ins> No(&'static [&'static str]), </ins> Invalid(String, &'static str), }

IsInFollow::Yes }, "stmt" | "expr"  => { <del> let tokens = vec!["`=>`", "`,`", "`;`"]; </del> <ins> const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"]; </ins> match tok { TokenTree::Token(token) => match token.kind { FatArrow | Comma | Semi => IsInFollow::Yes, <del> _ => IsInFollow::No(tokens), </del> <ins> _ => IsInFollow::No(TOKENS), </ins> }, <del> _ => IsInFollow::No(tokens), </del> <ins> _ => IsInFollow::No(TOKENS), </ins> } }, "pat" => { <del> let tokens = vec!["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"]; </del> <ins> const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"]; </ins> match tok { TokenTree::Token(token) => match token.kind { FatArrow | Comma | Eq | BinOp(token::Or) => IsInFollow::Yes, Ident(name, false) if name == kw::If || name == kw::In => IsInFollow::Yes, <del> _ => IsInFollow::No(tokens), </del> <ins> _ => IsInFollow::No(TOKENS), </ins> }, <del> _ => IsInFollow::No(tokens), </del> <ins> _ => IsInFollow::No(TOKENS), </ins> } }, "path" | "ty" => { <del> let tokens = vec![ </del> <ins> const TOKENS: &[&str] = &[ </ins> "`{`", "`[`", "`=>`", "`,`", "`>`","`=`", "`:`", "`;`", "`|`", "`as`", "`where`", ];

BinOp(token::Or) => IsInFollow::Yes, Ident(name, false) if name == kw::As || name == kw::Where => IsInFollow::Yes, <del> _ => IsInFollow::No(tokens), </del> <ins> _ => IsInFollow::No(TOKENS), </ins> }, TokenTree::MetaVarDecl(_, _, frag) if frag.name == sym::block => IsInFollow::Yes, <del> _ => IsInFollow::No(tokens), </del> <ins> _ => IsInFollow::No(TOKENS), </ins> } }, "ident" | "lifetime" => {

}, "vis" => { // Explicitly disallow `priv`, on the off chance it comes back. <del> let tokens = vec!["`,`", "an ident", "a type"]; </del> <ins> const TOKENS: &[&str] = &["`,`", "an ident", "a type"]; </ins> match tok { TokenTree::Token(token) => match token.kind { Comma => IsInFollow::Yes,

_ => if token.can_begin_type() { IsInFollow::Yes } else { <del> IsInFollow::No(tokens) </del> <ins> IsInFollow::No(TOKENS) </ins> } }, TokenTree::MetaVarDecl(_, _, frag) if frag.name == sym::ident || frag.name == sym::ty || frag.name == sym::path => IsInFollow::Yes, <del> _ => IsInFollow::No(tokens), </del> <ins> _ => IsInFollow::No(TOKENS), </ins> } }, "" => IsInFollow::Yes, // kw::Invalid