@@ -222,7 +222,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
222
222
if let MatchedNonterminal ( ref nt) = * m {
223
223
if let NtTT ( ref tt) = * * nt {
224
224
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) ;
226
226
return tt;
227
227
}
228
228
}
@@ -272,11 +272,12 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
272
272
273
273
fn check_lhs_nt_follows ( sess : & ParseSess ,
274
274
features : & RefCell < Features > ,
275
+ attrs : & [ ast:: Attribute ] ,
275
276
lhs : & quoted:: TokenTree ) -> bool {
276
277
// lhs is going to be like TokenTree::Delimited(...), where the
277
278
// entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
278
279
if let quoted:: TokenTree :: Delimited ( _, ref tts) = * lhs {
279
- check_matcher ( sess, features, & tts. tts )
280
+ check_matcher ( sess, features, attrs , & tts. tts )
280
281
} else {
281
282
let msg = "invalid macro matcher; matchers must be contained in balanced delimiters" ;
282
283
sess. span_diagnostic . span_err ( lhs. span ( ) , msg) ;
@@ -328,11 +329,12 @@ fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool {
328
329
329
330
fn check_matcher ( sess : & ParseSess ,
330
331
features : & RefCell < Features > ,
332
+ attrs : & [ ast:: Attribute ] ,
331
333
matcher : & [ quoted:: TokenTree ] ) -> bool {
332
334
let first_sets = FirstSets :: new ( matcher) ;
333
335
let empty_suffix = TokenSet :: empty ( ) ;
334
336
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) ;
336
338
err == sess. span_diagnostic . err_count ( )
337
339
}
338
340
@@ -575,6 +577,7 @@ impl TokenSet {
575
577
// see `FirstSets::new`.
576
578
fn check_matcher_core ( sess : & ParseSess ,
577
579
features : & RefCell < Features > ,
580
+ attrs : & [ ast:: Attribute ] ,
578
581
first_sets : & FirstSets ,
579
582
matcher : & [ quoted:: TokenTree ] ,
580
583
follow : & TokenSet ) -> TokenSet {
@@ -605,7 +608,7 @@ fn check_matcher_core(sess: &ParseSess,
605
608
match * token {
606
609
TokenTree :: Token ( ..) | TokenTree :: MetaVar ( ..) | TokenTree :: MetaVarDecl ( ..) => {
607
610
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) {
609
612
let msg = format ! ( "invalid fragment specifier `{}`" , bad_frag) ;
610
613
sess. span_diagnostic . struct_span_err ( token. span ( ) , & msg)
611
614
. help ( "valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, \
@@ -631,7 +634,7 @@ fn check_matcher_core(sess: &ParseSess,
631
634
}
632
635
TokenTree :: Delimited ( span, ref d) => {
633
636
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) ;
635
638
// don't track non NT tokens
636
639
last. replace_with_irrelevant ( ) ;
637
640
@@ -663,7 +666,12 @@ fn check_matcher_core(sess: &ParseSess,
663
666
// At this point, `suffix_first` is built, and
664
667
// `my_suffix` is some TokenSet that we can use
665
668
// 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) ;
667
675
if next. maybe_empty {
668
676
last. add_all ( & next) ;
669
677
} else {
@@ -836,12 +844,13 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result<bool, (String, &'
836
844
837
845
fn has_legal_fragment_specifier ( sess : & ParseSess ,
838
846
features : & RefCell < Features > ,
847
+ attrs : & [ ast:: Attribute ] ,
839
848
tok : & quoted:: TokenTree ) -> Result < ( ) , String > {
840
849
debug ! ( "has_legal_fragment_specifier({:?})" , tok) ;
841
850
if let quoted:: TokenTree :: MetaVarDecl ( _, _, ref frag_spec) = * tok {
842
851
let frag_name = frag_spec. name . as_str ( ) ;
843
852
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) {
845
854
return Err ( frag_name. to_string ( ) ) ;
846
855
}
847
856
}
@@ -850,13 +859,15 @@ fn has_legal_fragment_specifier(sess: &ParseSess,
850
859
851
860
fn is_legal_fragment_specifier ( sess : & ParseSess ,
852
861
features : & RefCell < Features > ,
862
+ attrs : & [ ast:: Attribute ] ,
853
863
frag_name : & str ,
854
864
frag_span : Span ) -> bool {
855
865
match frag_name {
856
866
"item" | "block" | "stmt" | "expr" | "pat" |
857
867
"path" | "ty" | "ident" | "meta" | "tt" | "" => true ,
858
868
"vis" => {
859
- if !features. borrow ( ) . macro_vis_matcher {
869
+ if !features. borrow ( ) . macro_vis_matcher
870
+ && !attr:: contains_name ( attrs, "allow_internal_unstable" ) {
860
871
let explain = feature_gate:: EXPLAIN_VIS_MATCHER ;
861
872
emit_feature_err ( sess,
862
873
"macro_vis_matcher" ,
0 commit comments