@@ -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