@@ -210,7 +210,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
210
210
if let MatchedNonterminal ( ref nt) = * * m {
211
211
if let NtTT ( ref tt) = * * nt {
212
212
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) ;
214
214
return tt;
215
215
}
216
216
}
@@ -255,11 +255,12 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
255
255
256
256
fn check_lhs_nt_follows ( sess : & ParseSess ,
257
257
features : & RefCell < Features > ,
258
+ attrs : & [ ast:: Attribute ] ,
258
259
lhs : & quoted:: TokenTree ) -> bool {
259
260
// lhs is going to be like TokenTree::Delimited(...), where the
260
261
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
261
262
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 ) ,
263
264
_ => {
264
265
let msg = "invalid macro matcher; matchers must be contained in balanced delimiters" ;
265
266
sess. span_diagnostic . span_err ( lhs. span ( ) , msg) ;
@@ -313,11 +314,12 @@ fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool {
313
314
314
315
fn check_matcher ( sess : & ParseSess ,
315
316
features : & RefCell < Features > ,
317
+ attrs : & [ ast:: Attribute ] ,
316
318
matcher : & [ quoted:: TokenTree ] ) -> bool {
317
319
let first_sets = FirstSets :: new ( matcher) ;
318
320
let empty_suffix = TokenSet :: empty ( ) ;
319
321
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) ;
321
323
err == sess. span_diagnostic . err_count ( )
322
324
}
323
325
@@ -560,6 +562,7 @@ impl TokenSet {
560
562
// see `FirstSets::new`.
561
563
fn check_matcher_core ( sess : & ParseSess ,
562
564
features : & RefCell < Features > ,
565
+ attrs : & [ ast:: Attribute ] ,
563
566
first_sets : & FirstSets ,
564
567
matcher : & [ quoted:: TokenTree ] ,
565
568
follow : & TokenSet ) -> TokenSet {
@@ -590,7 +593,7 @@ fn check_matcher_core(sess: &ParseSess,
590
593
match * token {
591
594
TokenTree :: Token ( ..) | TokenTree :: MetaVarDecl ( ..) => {
592
595
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) {
594
597
let msg = format ! ( "invalid fragment specifier `{}`" , bad_frag) ;
595
598
sess. span_diagnostic . struct_span_err ( token. span ( ) , & msg)
596
599
. help ( "valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, \
@@ -616,7 +619,7 @@ fn check_matcher_core(sess: &ParseSess,
616
619
}
617
620
TokenTree :: Delimited ( span, ref d) => {
618
621
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) ;
620
623
// don't track non NT tokens
621
624
last. replace_with_irrelevant ( ) ;
622
625
@@ -648,7 +651,12 @@ fn check_matcher_core(sess: &ParseSess,
648
651
// At this point, `suffix_first` is built, and
649
652
// `my_suffix` is some TokenSet that we can use
650
653
// 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) ;
652
660
if next. maybe_empty {
653
661
last. add_all ( & next) ;
654
662
} else {
@@ -821,12 +829,13 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result<bool, (String, &'
821
829
822
830
fn has_legal_fragment_specifier ( sess : & ParseSess ,
823
831
features : & RefCell < Features > ,
832
+ attrs : & [ ast:: Attribute ] ,
824
833
tok : & quoted:: TokenTree ) -> Result < ( ) , String > {
825
834
debug ! ( "has_legal_fragment_specifier({:?})" , tok) ;
826
835
if let quoted:: TokenTree :: MetaVarDecl ( _, _, ref frag_spec) = * tok {
827
836
let frag_name = frag_spec. name . as_str ( ) ;
828
837
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) {
830
839
return Err ( frag_name. to_string ( ) ) ;
831
840
}
832
841
}
@@ -835,13 +844,15 @@ fn has_legal_fragment_specifier(sess: &ParseSess,
835
844
836
845
fn is_legal_fragment_specifier ( sess : & ParseSess ,
837
846
features : & RefCell < Features > ,
847
+ attrs : & [ ast:: Attribute ] ,
838
848
frag_name : & str ,
839
849
frag_span : Span ) -> bool {
840
850
match frag_name {
841
851
"item" | "block" | "stmt" | "expr" | "pat" |
842
852
"path" | "ty" | "ident" | "meta" | "tt" | "" => true ,
843
853
"vis" => {
844
- if !features. borrow ( ) . macro_vis_matcher {
854
+ if !features. borrow ( ) . macro_vis_matcher
855
+ && !attr:: contains_name ( attrs, "allow_internal_unstable" ) {
845
856
let explain = feature_gate:: EXPLAIN_VIS_MATCHER ;
846
857
emit_feature_err ( sess,
847
858
"macro_vis_matcher" ,
0 commit comments