@@ -32,15 +32,10 @@ pub enum Stability {
3232 Deprecated ( & ' static str , Option < & ' static str > ) ,
3333}
3434
35- struct Context < ' a > {
36- parse_sess : & ' a ParseSess ,
37- features : & ' a Features ,
38- }
39-
4035macro_rules! gate_feature_fn {
4136 ( $cx: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $level: expr) => { {
4237 let ( cx, has_feature, span,
43- name, explain, level) = ( $cx, $has_feature, $span, $name, $explain, $level) ;
38+ name, explain, level) = ( & * $cx, $has_feature, $span, $name, $explain, $level) ;
4439 let has_feature: bool = has_feature( & $cx. features) ;
4540 debug!( "gate_feature(feature = {:?}, span = {:?}); has? {}" , name, span, has_feature) ;
4641 if !has_feature && !span. allows_unstable( $name) {
@@ -62,45 +57,7 @@ macro_rules! gate_feature {
6257}
6358
6459crate fn check_attribute ( attr : & ast:: Attribute , parse_sess : & ParseSess , features : & Features ) {
65- let cx = & Context { parse_sess, features } ;
66- let attr_info =
67- attr. ident ( ) . and_then ( |ident| BUILTIN_ATTRIBUTE_MAP . get ( & ident. name ) ) . map ( |a| * * a) ;
68- // Check feature gates for built-in attributes.
69- if let Some ( ( .., AttributeGate :: Gated ( _, name, descr, has_feature) ) ) = attr_info {
70- gate_feature_fn ! ( cx, has_feature, attr. span, name, descr, GateStrength :: Hard ) ;
71- }
72- // Check input tokens for built-in and key-value attributes.
73- match attr_info {
74- // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
75- Some ( ( name, _, template, _) ) if name != sym:: rustc_dummy =>
76- check_builtin_attribute ( parse_sess, attr, name, template) ,
77- _ => if let Some ( TokenTree :: Token ( token) ) = attr. tokens . trees ( ) . next ( ) {
78- if token == token:: Eq {
79- // All key-value attributes are restricted to meta-item syntax.
80- attr. parse_meta ( parse_sess) . map_err ( |mut err| err. emit ( ) ) . ok ( ) ;
81- }
82- }
83- }
84- // Check unstable flavors of the `#[doc]` attribute.
85- if attr. check_name ( sym:: doc) {
86- for nested_meta in attr. meta_item_list ( ) . unwrap_or_default ( ) {
87- macro_rules! gate_doc { ( $( $name: ident => $feature: ident) * ) => {
88- $( if nested_meta. check_name( sym:: $name) {
89- let msg = concat!( "`#[doc(" , stringify!( $name) , ")]` is experimental" ) ;
90- gate_feature!( cx, $feature, attr. span, msg) ;
91- } ) *
92- } }
93-
94- gate_doc ! (
95- include => external_doc
96- cfg => doc_cfg
97- masked => doc_masked
98- spotlight => doc_spotlight
99- alias => doc_alias
100- keyword => doc_keyword
101- ) ;
102- }
103- }
60+ PostExpansionVisitor { parse_sess, features } . visit_attribute ( attr)
10461}
10562
10663fn find_lang_feature_issue ( feature : Symbol ) -> Option < u32 > {
@@ -215,20 +172,21 @@ pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &str =
215172 "unsized tuple coercion is not stable enough for use and is subject to change" ;
216173
217174struct PostExpansionVisitor < ' a > {
218- context : & ' a Context < ' a > ,
175+ parse_sess : & ' a ParseSess ,
176+ features : & ' a Features ,
219177}
220178
221179macro_rules! gate_feature_post {
222180 ( $cx: expr, $feature: ident, $span: expr, $explain: expr) => { {
223181 let ( cx, span) = ( $cx, $span) ;
224182 if !span. allows_unstable( sym:: $feature) {
225- gate_feature!( cx. context , $feature, span, $explain)
183+ gate_feature!( cx, $feature, span, $explain)
226184 }
227185 } } ;
228186 ( $cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => { {
229187 let ( cx, span) = ( $cx, $span) ;
230188 if !span. allows_unstable( sym:: $feature) {
231- gate_feature!( cx. context , $feature, span, $explain, $level)
189+ gate_feature!( cx, $feature, span, $explain, $level)
232190 }
233191 } }
234192}
@@ -292,15 +250,52 @@ impl<'a> PostExpansionVisitor<'a> {
292250
293251impl < ' a > Visitor < ' a > for PostExpansionVisitor < ' a > {
294252 fn visit_attribute ( & mut self , attr : & ast:: Attribute ) {
295- check_attribute ( attr, self . context . parse_sess , self . context . features ) ;
253+ let attr_info =
254+ attr. ident ( ) . and_then ( |ident| BUILTIN_ATTRIBUTE_MAP . get ( & ident. name ) ) . map ( |a| * * a) ;
255+ // Check feature gates for built-in attributes.
256+ if let Some ( ( .., AttributeGate :: Gated ( _, name, descr, has_feature) ) ) = attr_info {
257+ gate_feature_fn ! ( self , has_feature, attr. span, name, descr, GateStrength :: Hard ) ;
258+ }
259+ // Check input tokens for built-in and key-value attributes.
260+ match attr_info {
261+ // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
262+ Some ( ( name, _, template, _) ) if name != sym:: rustc_dummy =>
263+ check_builtin_attribute ( self . parse_sess , attr, name, template) ,
264+ _ => if let Some ( TokenTree :: Token ( token) ) = attr. tokens . trees ( ) . next ( ) {
265+ if token == token:: Eq {
266+ // All key-value attributes are restricted to meta-item syntax.
267+ attr. parse_meta ( self . parse_sess ) . map_err ( |mut err| err. emit ( ) ) . ok ( ) ;
268+ }
269+ }
270+ }
271+ // Check unstable flavors of the `#[doc]` attribute.
272+ if attr. check_name ( sym:: doc) {
273+ for nested_meta in attr. meta_item_list ( ) . unwrap_or_default ( ) {
274+ macro_rules! gate_doc { ( $( $name: ident => $feature: ident) * ) => {
275+ $( if nested_meta. check_name( sym:: $name) {
276+ let msg = concat!( "`#[doc(" , stringify!( $name) , ")]` is experimental" ) ;
277+ gate_feature!( self , $feature, attr. span, msg) ;
278+ } ) *
279+ } }
280+
281+ gate_doc ! (
282+ include => external_doc
283+ cfg => doc_cfg
284+ masked => doc_masked
285+ spotlight => doc_spotlight
286+ alias => doc_alias
287+ keyword => doc_keyword
288+ ) ;
289+ }
290+ }
296291 }
297292
298293 fn visit_name ( & mut self , sp : Span , name : ast:: Name ) {
299294 if !name. as_str ( ) . is_ascii ( ) {
300295 gate_feature_post ! (
301296 & self ,
302297 non_ascii_idents,
303- self . context . parse_sess. source_map( ) . def_span( sp) ,
298+ self . parse_sess. source_map( ) . def_span( sp) ,
304299 "non-ascii idents are not fully supported"
305300 ) ;
306301 }
@@ -356,12 +351,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
356351 }
357352 }
358353
359- let has_feature = self . context . features . arbitrary_enum_discriminant ;
354+ let has_feature = self . features . arbitrary_enum_discriminant ;
360355 if !has_feature && !i. span . allows_unstable ( sym:: arbitrary_enum_discriminant) {
361- Parser :: maybe_report_invalid_custom_discriminants (
362- self . context . parse_sess ,
363- & variants,
364- ) ;
356+ Parser :: maybe_report_invalid_custom_discriminants ( self . parse_sess , & variants) ;
365357 }
366358 }
367359
@@ -471,7 +463,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
471463 ast:: ExprKind :: Type ( ..) => {
472464 // To avoid noise about type ascription in common syntax errors, only emit if it
473465 // is the *only* error.
474- if self . context . parse_sess . span_diagnostic . err_count ( ) == 0 {
466+ if self . parse_sess . span_diagnostic . err_count ( ) == 0 {
475467 gate_feature_post ! ( & self , type_ascription, e. span,
476468 "type ascription is experimental" ) ;
477469 }
@@ -809,13 +801,13 @@ pub fn check_crate(krate: &ast::Crate,
809801 features : & Features ,
810802 unstable : UnstableFeatures ) {
811803 maybe_stage_features ( & parse_sess. span_diagnostic , krate, unstable) ;
812- let ctx = Context { parse_sess, features } ;
804+ let mut visitor = PostExpansionVisitor { parse_sess, features } ;
813805
814806 macro_rules! gate_all {
815807 ( $gate: ident, $msg: literal) => { gate_all!( $gate, $gate, $msg) ; } ;
816808 ( $spans: ident, $gate: ident, $msg: literal) => {
817809 for span in & * parse_sess. gated_spans. $spans. borrow( ) {
818- gate_feature!( & ctx , $gate, * span, $msg) ;
810+ gate_feature!( & visitor , $gate, * span, $msg) ;
819811 }
820812 }
821813 }
@@ -826,7 +818,7 @@ pub fn check_crate(krate: &ast::Crate,
826818 gate_all ! ( yields, generators, "yield syntax is experimental" ) ;
827819 gate_all ! ( or_patterns, "or-patterns syntax is experimental" ) ;
828820
829- visit:: walk_crate ( & mut PostExpansionVisitor { context : & ctx } , krate) ;
821+ visit:: walk_crate ( & mut visitor , krate) ;
830822}
831823
832824#[ derive( Clone , Copy , Hash ) ]
0 commit comments