@@ -222,7 +222,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
222222 if let MatchedNonterminal ( ref nt) = * m {
223223 if let NtTT ( ref tt) = * * nt {
224224 let tt = quoted:: parse ( tt. clone ( ) . into ( ) , true , sess) . pop ( ) . unwrap ( ) ;
225- valid &= check_lhs_nt_follows ( sess, features, & tt) ;
225+ valid &= check_lhs_nt_follows ( sess, features, & def . attrs , & tt) ;
226226 return tt;
227227 }
228228 }
@@ -272,11 +272,12 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
272272
273273fn check_lhs_nt_follows ( sess : & ParseSess ,
274274 features : & RefCell < Features > ,
275+ attrs : & [ ast:: Attribute ] ,
275276 lhs : & quoted:: TokenTree ) -> bool {
276277 // lhs is going to be like TokenTree::Delimited(...), where the
277278 // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
278279 if let quoted:: TokenTree :: Delimited ( _, ref tts) = * lhs {
279- check_matcher ( sess, features, & tts. tts )
280+ check_matcher ( sess, features, attrs , & tts. tts )
280281 } else {
281282 let msg = "invalid macro matcher; matchers must be contained in balanced delimiters" ;
282283 sess. span_diagnostic . span_err ( lhs. span ( ) , msg) ;
@@ -328,11 +329,12 @@ fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool {
328329
329330fn check_matcher ( sess : & ParseSess ,
330331 features : & RefCell < Features > ,
332+ attrs : & [ ast:: Attribute ] ,
331333 matcher : & [ quoted:: TokenTree ] ) -> bool {
332334 let first_sets = FirstSets :: new ( matcher) ;
333335 let empty_suffix = TokenSet :: empty ( ) ;
334336 let err = sess. span_diagnostic . err_count ( ) ;
335- check_matcher_core ( sess, features, & first_sets, matcher, & empty_suffix) ;
337+ check_matcher_core ( sess, features, attrs , & first_sets, matcher, & empty_suffix) ;
336338 err == sess. span_diagnostic . err_count ( )
337339}
338340
@@ -575,6 +577,7 @@ impl TokenSet {
575577// see `FirstSets::new`.
576578fn check_matcher_core ( sess : & ParseSess ,
577579 features : & RefCell < Features > ,
580+ attrs : & [ ast:: Attribute ] ,
578581 first_sets : & FirstSets ,
579582 matcher : & [ quoted:: TokenTree ] ,
580583 follow : & TokenSet ) -> TokenSet {
@@ -605,7 +608,7 @@ fn check_matcher_core(sess: &ParseSess,
605608 match * token {
606609 TokenTree :: Token ( ..) | TokenTree :: MetaVar ( ..) | TokenTree :: MetaVarDecl ( ..) => {
607610 let can_be_followed_by_any;
608- if let Err ( bad_frag) = has_legal_fragment_specifier ( sess, features, token) {
611+ if let Err ( bad_frag) = has_legal_fragment_specifier ( sess, features, attrs , token) {
609612 let msg = format ! ( "invalid fragment specifier `{}`" , bad_frag) ;
610613 sess. span_diagnostic . struct_span_err ( token. span ( ) , & msg)
611614 . help ( "valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, \
@@ -631,7 +634,7 @@ fn check_matcher_core(sess: &ParseSess,
631634 }
632635 TokenTree :: Delimited ( span, ref d) => {
633636 let my_suffix = TokenSet :: singleton ( d. close_tt ( span) ) ;
634- check_matcher_core ( sess, features, first_sets, & d. tts , & my_suffix) ;
637+ check_matcher_core ( sess, features, attrs , first_sets, & d. tts , & my_suffix) ;
635638 // don't track non NT tokens
636639 last. replace_with_irrelevant ( ) ;
637640
@@ -663,7 +666,12 @@ fn check_matcher_core(sess: &ParseSess,
663666 // At this point, `suffix_first` is built, and
664667 // `my_suffix` is some TokenSet that we can use
665668 // for checking the interior of `seq_rep`.
666- let next = check_matcher_core ( sess, features, first_sets, & seq_rep. tts , my_suffix) ;
669+ let next = check_matcher_core ( sess,
670+ features,
671+ attrs,
672+ first_sets,
673+ & seq_rep. tts ,
674+ my_suffix) ;
667675 if next. maybe_empty {
668676 last. add_all ( & next) ;
669677 } else {
@@ -836,12 +844,13 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result<bool, (String, &'
836844
837845fn has_legal_fragment_specifier ( sess : & ParseSess ,
838846 features : & RefCell < Features > ,
847+ attrs : & [ ast:: Attribute ] ,
839848 tok : & quoted:: TokenTree ) -> Result < ( ) , String > {
840849 debug ! ( "has_legal_fragment_specifier({:?})" , tok) ;
841850 if let quoted:: TokenTree :: MetaVarDecl ( _, _, ref frag_spec) = * tok {
842851 let frag_name = frag_spec. name . as_str ( ) ;
843852 let frag_span = tok. span ( ) ;
844- if !is_legal_fragment_specifier ( sess, features, & frag_name, frag_span) {
853+ if !is_legal_fragment_specifier ( sess, features, attrs , & frag_name, frag_span) {
845854 return Err ( frag_name. to_string ( ) ) ;
846855 }
847856 }
@@ -850,13 +859,15 @@ fn has_legal_fragment_specifier(sess: &ParseSess,
850859
851860fn is_legal_fragment_specifier ( sess : & ParseSess ,
852861 features : & RefCell < Features > ,
862+ attrs : & [ ast:: Attribute ] ,
853863 frag_name : & str ,
854864 frag_span : Span ) -> bool {
855865 match frag_name {
856866 "item" | "block" | "stmt" | "expr" | "pat" |
857867 "path" | "ty" | "ident" | "meta" | "tt" | "" => true ,
858868 "vis" => {
859- if !features. borrow ( ) . macro_vis_matcher {
869+ if !features. borrow ( ) . macro_vis_matcher
870+ && !attr:: contains_name ( attrs, "allow_internal_unstable" ) {
860871 let explain = feature_gate:: EXPLAIN_VIS_MATCHER ;
861872 emit_feature_err ( sess,
862873 "macro_vis_matcher" ,
0 commit comments