@@ -210,7 +210,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
210210 if let MatchedNonterminal ( ref nt) = * * m {
211211 if let NtTT ( ref tt) = * * nt {
212212 let tt = quoted:: parse ( tt. clone ( ) . into ( ) , true , sess) . pop ( ) . unwrap ( ) ;
213- valid &= check_lhs_nt_follows ( sess, features, & tt) ;
213+ valid &= check_lhs_nt_follows ( sess, features, & def . attrs , & tt) ;
214214 return tt;
215215 }
216216 }
@@ -255,11 +255,12 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
255255
256256fn check_lhs_nt_follows ( sess : & ParseSess ,
257257 features : & RefCell < Features > ,
258+ attrs : & [ ast:: Attribute ] ,
258259 lhs : & quoted:: TokenTree ) -> bool {
259260 // lhs is going to be like TokenTree::Delimited(...), where the
260261 // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
261262 match lhs {
262- & quoted:: TokenTree :: Delimited ( _, ref tts) => check_matcher ( sess, features, & tts. tts ) ,
263+ & quoted:: TokenTree :: Delimited ( _, ref tts) => check_matcher ( sess, features, attrs , & tts. tts ) ,
263264 _ => {
264265 let msg = "invalid macro matcher; matchers must be contained in balanced delimiters" ;
265266 sess. span_diagnostic . span_err ( lhs. span ( ) , msg) ;
@@ -313,11 +314,12 @@ fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool {
313314
314315fn check_matcher ( sess : & ParseSess ,
315316 features : & RefCell < Features > ,
317+ attrs : & [ ast:: Attribute ] ,
316318 matcher : & [ quoted:: TokenTree ] ) -> bool {
317319 let first_sets = FirstSets :: new ( matcher) ;
318320 let empty_suffix = TokenSet :: empty ( ) ;
319321 let err = sess. span_diagnostic . err_count ( ) ;
320- check_matcher_core ( sess, features, & first_sets, matcher, & empty_suffix) ;
322+ check_matcher_core ( sess, features, attrs , & first_sets, matcher, & empty_suffix) ;
321323 err == sess. span_diagnostic . err_count ( )
322324}
323325
@@ -560,6 +562,7 @@ impl TokenSet {
560562// see `FirstSets::new`.
561563fn check_matcher_core ( sess : & ParseSess ,
562564 features : & RefCell < Features > ,
565+ attrs : & [ ast:: Attribute ] ,
563566 first_sets : & FirstSets ,
564567 matcher : & [ quoted:: TokenTree ] ,
565568 follow : & TokenSet ) -> TokenSet {
@@ -590,7 +593,7 @@ fn check_matcher_core(sess: &ParseSess,
590593 match * token {
591594 TokenTree :: Token ( ..) | TokenTree :: MetaVarDecl ( ..) => {
592595 let can_be_followed_by_any;
593- if let Err ( bad_frag) = has_legal_fragment_specifier ( sess, features, token) {
596+ if let Err ( bad_frag) = has_legal_fragment_specifier ( sess, features, attrs , token) {
594597 let msg = format ! ( "invalid fragment specifier `{}`" , bad_frag) ;
595598 sess. span_diagnostic . struct_span_err ( token. span ( ) , & msg)
596599 . help ( "valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, \
@@ -616,7 +619,7 @@ fn check_matcher_core(sess: &ParseSess,
616619 }
617620 TokenTree :: Delimited ( span, ref d) => {
618621 let my_suffix = TokenSet :: singleton ( d. close_tt ( span) ) ;
619- check_matcher_core ( sess, features, first_sets, & d. tts , & my_suffix) ;
622+ check_matcher_core ( sess, features, attrs , first_sets, & d. tts , & my_suffix) ;
620623 // don't track non NT tokens
621624 last. replace_with_irrelevant ( ) ;
622625
@@ -648,7 +651,12 @@ fn check_matcher_core(sess: &ParseSess,
648651 // At this point, `suffix_first` is built, and
649652 // `my_suffix` is some TokenSet that we can use
650653 // for checking the interior of `seq_rep`.
651- let next = check_matcher_core ( sess, features, first_sets, & seq_rep. tts , my_suffix) ;
654+ let next = check_matcher_core ( sess,
655+ features,
656+ attrs,
657+ first_sets,
658+ & seq_rep. tts ,
659+ my_suffix) ;
652660 if next. maybe_empty {
653661 last. add_all ( & next) ;
654662 } else {
@@ -821,12 +829,13 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result<bool, (String, &'
821829
822830fn has_legal_fragment_specifier ( sess : & ParseSess ,
823831 features : & RefCell < Features > ,
832+ attrs : & [ ast:: Attribute ] ,
824833 tok : & quoted:: TokenTree ) -> Result < ( ) , String > {
825834 debug ! ( "has_legal_fragment_specifier({:?})" , tok) ;
826835 if let quoted:: TokenTree :: MetaVarDecl ( _, _, ref frag_spec) = * tok {
827836 let frag_name = frag_spec. name . as_str ( ) ;
828837 let frag_span = tok. span ( ) ;
829- if !is_legal_fragment_specifier ( sess, features, & frag_name, frag_span) {
838+ if !is_legal_fragment_specifier ( sess, features, attrs , & frag_name, frag_span) {
830839 return Err ( frag_name. to_string ( ) ) ;
831840 }
832841 }
@@ -835,13 +844,15 @@ fn has_legal_fragment_specifier(sess: &ParseSess,
835844
836845fn is_legal_fragment_specifier ( sess : & ParseSess ,
837846 features : & RefCell < Features > ,
847+ attrs : & [ ast:: Attribute ] ,
838848 frag_name : & str ,
839849 frag_span : Span ) -> bool {
840850 match frag_name {
841851 "item" | "block" | "stmt" | "expr" | "pat" |
842852 "path" | "ty" | "ident" | "meta" | "tt" | "" => true ,
843853 "vis" => {
844- if !features. borrow ( ) . macro_vis_matcher {
854+ if !features. borrow ( ) . macro_vis_matcher
855+ && !attr:: contains_name ( attrs, "allow_internal_unstable" ) {
845856 let explain = feature_gate:: EXPLAIN_VIS_MATCHER ;
846857 emit_feature_err ( sess,
847858 "macro_vis_matcher" ,
0 commit comments