@@ -3,7 +3,7 @@ use std::num::IntErrorKind;
33use rustc_hir:: limit:: Limit ;
44
55use super :: prelude:: * ;
6- use crate :: session_diagnostics:: { FeatureExpectedSingleWord , LimitInvalid } ;
6+ use crate :: session_diagnostics:: { ExpectedSingleWord , LimitInvalid } ;
77
88impl < S : Stage > AcceptContext < ' _ , ' _ , S > {
99 fn parse_limit_int ( & self , nv : & NameValueParser ) -> Option < Limit > {
@@ -221,7 +221,64 @@ impl<S: Stage> CombineAttributeParser<S> for FeatureParser {
221221 let path = elem. path ( ) ;
222222 let Some ( ident) = path. word ( ) else {
223223 let first_segment = elem. path ( ) . segments ( ) . next ( ) . expect ( "at least one segment" ) ;
224- cx. emit_err ( FeatureExpectedSingleWord {
224+ cx. emit_err ( ExpectedSingleWord {
225+ description : "rust features" ,
226+ span : path. span ( ) ,
227+ first_segment_span : first_segment. span ,
228+ first_segment : first_segment. name ,
229+ } ) ;
230+ continue ;
231+ } ;
232+
233+ res. push ( ident) ;
234+ }
235+
236+ res
237+ }
238+ }
239+
240+ pub ( crate ) struct RegisterToolParser ;
241+
242+ impl < S : Stage > CombineAttributeParser < S > for RegisterToolParser {
243+ const PATH : & [ Symbol ] = & [ sym:: register_tool] ;
244+ type Item = Ident ;
245+ const CONVERT : ConvertFn < Self :: Item > = AttributeKind :: RegisterTool ;
246+
247+ // FIXME: recursion limit is allowed on all targets and ignored,
248+ // even though it should only be valid on crates of course
249+ const ALLOWED_TARGETS : AllowedTargets = AllowedTargets :: AllowList ( ALL_TARGETS ) ;
250+ const TEMPLATE : AttributeTemplate = template ! ( List : & [ "tool1, tool2, ..." ] ) ;
251+
252+ fn extend < ' c > (
253+ cx : & ' c mut AcceptContext < ' _ , ' _ , S > ,
254+ args : & ' c ArgParser < ' _ > ,
255+ ) -> impl IntoIterator < Item = Self :: Item > + ' c {
256+ let ArgParser :: List ( list) = args else {
257+ cx. expected_list ( cx. attr_span ) ;
258+ return Vec :: new ( ) ;
259+ } ;
260+
261+ if list. is_empty ( ) {
262+ cx. warn_empty_attribute ( cx. attr_span ) ;
263+ }
264+
265+ let mut res = Vec :: new ( ) ;
266+
267+ for elem in list. mixed ( ) {
268+ let Some ( elem) = elem. meta_item ( ) else {
269+ cx. expected_identifier ( elem. span ( ) ) ;
270+ continue ;
271+ } ;
272+ if let Err ( arg_span) = elem. args ( ) . no_args ( ) {
273+ cx. expected_no_args ( arg_span) ;
274+ continue ;
275+ }
276+
277+ let path = elem. path ( ) ;
278+ let Some ( ident) = path. word ( ) else {
279+ let first_segment = elem. path ( ) . segments ( ) . next ( ) . expect ( "at least one segment" ) ;
280+ cx. emit_err ( ExpectedSingleWord {
281+ description : "tools" ,
225282 span : path. span ( ) ,
226283 first_segment_span : first_segment. span ,
227284 first_segment : first_segment. name ,
0 commit comments