@@ -5,6 +5,7 @@ use rustc_attr_data_structures::{
5
5
StableSince , UnstableReason , VERSION_PLACEHOLDER ,
6
6
} ;
7
7
use rustc_errors:: ErrorGuaranteed ;
8
+ use rustc_feature:: { AttributeTemplate , template} ;
8
9
use rustc_span:: { Span , Symbol , sym} ;
9
10
10
11
use super :: util:: parse_version;
@@ -43,26 +44,39 @@ impl StabilityParser {
43
44
44
45
impl < S : Stage > AttributeParser < S > for StabilityParser {
45
46
const ATTRIBUTES : AcceptMapping < Self , S > = & [
46
- ( & [ sym:: stable] , |this, cx, args| {
47
- reject_outside_std ! ( cx) ;
48
- if !this. check_duplicate ( cx)
49
- && let Some ( ( feature, level) ) = parse_stability ( cx, args)
50
- {
51
- this. stability = Some ( ( Stability { level, feature } , cx. attr_span ) ) ;
52
- }
53
- } ) ,
54
- ( & [ sym:: unstable] , |this, cx, args| {
55
- reject_outside_std ! ( cx) ;
56
- if !this. check_duplicate ( cx)
57
- && let Some ( ( feature, level) ) = parse_unstability ( cx, args)
58
- {
59
- this. stability = Some ( ( Stability { level, feature } , cx. attr_span ) ) ;
60
- }
61
- } ) ,
62
- ( & [ sym:: rustc_allowed_through_unstable_modules] , |this, cx, args| {
63
- reject_outside_std ! ( cx) ;
64
- this. allowed_through_unstable_modules = args. name_value ( ) . and_then ( |i| i. value_as_str ( ) )
65
- } ) ,
47
+ (
48
+ & [ sym:: stable] ,
49
+ template ! ( List : r#"feature = "name", since = "version""# ) ,
50
+ |this, cx, args| {
51
+ reject_outside_std ! ( cx) ;
52
+ if !this. check_duplicate ( cx)
53
+ && let Some ( ( feature, level) ) = parse_stability ( cx, args)
54
+ {
55
+ this. stability = Some ( ( Stability { level, feature } , cx. attr_span ) ) ;
56
+ }
57
+ } ,
58
+ ) ,
59
+ (
60
+ & [ sym:: unstable] ,
61
+ template ! ( List : r#"feature = "name", reason = "...", issue = "N""# ) ,
62
+ |this, cx, args| {
63
+ reject_outside_std ! ( cx) ;
64
+ if !this. check_duplicate ( cx)
65
+ && let Some ( ( feature, level) ) = parse_unstability ( cx, args)
66
+ {
67
+ this. stability = Some ( ( Stability { level, feature } , cx. attr_span ) ) ;
68
+ }
69
+ } ,
70
+ ) ,
71
+ (
72
+ & [ sym:: rustc_allowed_through_unstable_modules] ,
73
+ template ! ( NameValueStr : "deprecation message" ) ,
74
+ |this, cx, args| {
75
+ reject_outside_std ! ( cx) ;
76
+ this. allowed_through_unstable_modules =
77
+ args. name_value ( ) . and_then ( |i| i. value_as_str ( ) )
78
+ } ,
79
+ ) ,
66
80
] ;
67
81
68
82
fn finalize ( mut self , cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
@@ -96,16 +110,19 @@ pub(crate) struct BodyStabilityParser {
96
110
}
97
111
98
112
impl < S : Stage > AttributeParser < S > for BodyStabilityParser {
99
- const ATTRIBUTES : AcceptMapping < Self , S > =
100
- & [ ( & [ sym:: rustc_default_body_unstable] , |this, cx, args| {
113
+ const ATTRIBUTES : AcceptMapping < Self , S > = & [ (
114
+ & [ sym:: rustc_default_body_unstable] ,
115
+ template ! ( List : r#"feature = "name", reason = "...", issue = "N""# ) ,
116
+ |this, cx, args| {
101
117
reject_outside_std ! ( cx) ;
102
118
if this. stability . is_some ( ) {
103
119
cx. dcx ( )
104
120
. emit_err ( session_diagnostics:: MultipleStabilityLevels { span : cx. attr_span } ) ;
105
121
} else if let Some ( ( feature, level) ) = parse_unstability ( cx, args) {
106
122
this. stability = Some ( ( DefaultBodyStability { level, feature } , cx. attr_span ) ) ;
107
123
}
108
- } ) ] ;
124
+ } ,
125
+ ) ] ;
109
126
110
127
fn finalize ( self , _cx : & FinalizeContext < ' _ , ' _ , S > ) -> Option < AttributeKind > {
111
128
let ( stability, span) = self . stability ?;
@@ -120,6 +137,7 @@ impl<S: Stage> SingleAttributeParser<S> for ConstStabilityIndirectParser {
120
137
const PATH : & [ Symbol ] = & [ sym:: rustc_const_stable_indirect] ;
121
138
const ATTRIBUTE_ORDER : AttributeOrder = AttributeOrder :: KeepFirst ;
122
139
const ON_DUPLICATE : OnDuplicate < S > = OnDuplicate :: Ignore ;
140
+ const TEMPLATE : AttributeTemplate = template ! ( Word ) ;
123
141
124
142
fn convert ( _cx : & mut AcceptContext < ' _ , ' _ , S > , _args : & ArgParser < ' _ > ) -> Option < AttributeKind > {
125
143
Some ( AttributeKind :: ConstStabilityIndirect )
@@ -146,7 +164,7 @@ impl ConstStabilityParser {
146
164
147
165
impl < S : Stage > AttributeParser < S > for ConstStabilityParser {
148
166
const ATTRIBUTES : AcceptMapping < Self , S > = & [
149
- ( & [ sym:: rustc_const_stable] , |this, cx, args| {
167
+ ( & [ sym:: rustc_const_stable] , template ! ( List : r#"feature = "name""# ) , |this, cx, args| {
150
168
reject_outside_std ! ( cx) ;
151
169
152
170
if !this. check_duplicate ( cx)
@@ -158,7 +176,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
158
176
) ) ;
159
177
}
160
178
} ) ,
161
- ( & [ sym:: rustc_const_unstable] , |this, cx, args| {
179
+ ( & [ sym:: rustc_const_unstable] , template ! ( List : r#"feature = "name""# ) , |this, cx, args| {
162
180
reject_outside_std ! ( cx) ;
163
181
if !this. check_duplicate ( cx)
164
182
&& let Some ( ( feature, level) ) = parse_unstability ( cx, args)
@@ -169,7 +187,7 @@ impl<S: Stage> AttributeParser<S> for ConstStabilityParser {
169
187
) ) ;
170
188
}
171
189
} ) ,
172
- ( & [ sym:: rustc_promotable] , |this, cx, _| {
190
+ ( & [ sym:: rustc_promotable] , template ! ( Word ) , |this, cx, _| {
173
191
reject_outside_std ! ( cx) ;
174
192
this. promotable = true ;
175
193
} ) ,
0 commit comments