@@ -44,11 +44,41 @@ pub fn parse_cfg<S: Stage>(
4444 args : & ArgParser ,
4545) -> Option < CfgEntry > {
4646 let ArgParser :: List ( list) = args else {
47- cx. expected_list ( cx. attr_span , args) ;
47+ let attr_span = cx. attr_span ;
48+ cx. adcx ( ) . expected_list ( attr_span, args) ;
4849 return None ;
4950 } ;
51+
5052 let Some ( single) = list. single ( ) else {
51- cx. expected_single_argument ( list. span ) ;
53+ let target = cx. target ;
54+ let mut adcx = cx. adcx ( ) ;
55+ if list. is_empty ( ) {
56+ // `#[cfg()]`
57+ let message = format ! ( "if the {target} should be disabled, use `#[cfg(false)]`" ) ;
58+ adcx. push_suggestion ( message, list. span , "(false)" . to_string ( ) ) ;
59+ } else {
60+ // `#[cfg(foo, bar)]`
61+ if let Ok ( args) = adcx
62+ . sess ( )
63+ . source_map ( )
64+ . span_to_source ( list. span , |src, start, end| Ok ( src[ start..end] . to_string ( ) ) )
65+ {
66+ let all = format ! ( "(all{args})" ) ;
67+ let any = format ! ( "(any{args})" ) ;
68+
69+ let all_msg = format ! (
70+ "if the {target} should be enabled when all these predicates are, wrap them in `all`"
71+ ) ;
72+ let any_msg = format ! (
73+ "alternately, if the {target} should be enabled when any of these predicates are, wrap them in `any`"
74+ ) ;
75+
76+ adcx. push_suggestion ( all_msg, list. span , all) ;
77+ adcx. push_suggestion ( any_msg, list. span , any) ;
78+ }
79+ }
80+
81+ adcx. expected_single_argument ( list. span ) ;
5282 return None ;
5383 } ;
5484 parse_cfg_entry ( cx, single) . ok ( )
@@ -63,7 +93,7 @@ pub fn parse_cfg_entry<S: Stage>(
6393 ArgParser :: List ( list) => match meta. path ( ) . word_sym ( ) {
6494 Some ( sym:: not) => {
6595 let Some ( single) = list. single ( ) else {
66- return Err ( cx. expected_single_argument ( list. span ) ) ;
96+ return Err ( cx. adcx ( ) . expected_single_argument ( list. span ) ) ;
6797 } ;
6898 CfgEntry :: Not ( Box :: new ( parse_cfg_entry ( cx, single) ?) , list. span )
6999 }
@@ -87,14 +117,14 @@ pub fn parse_cfg_entry<S: Stage>(
87117 a @ ( ArgParser :: NoArgs | ArgParser :: NameValue ( _) ) => {
88118 let Some ( name) = meta. path ( ) . word_sym ( ) . filter ( |s| !s. is_path_segment_keyword ( ) )
89119 else {
90- return Err ( cx. expected_identifier ( meta. path ( ) . span ( ) ) ) ;
120+ return Err ( cx. adcx ( ) . expected_identifier ( meta. path ( ) . span ( ) ) ) ;
91121 } ;
92122 parse_name_value ( name, meta. path ( ) . span ( ) , a. name_value ( ) , meta. span ( ) , cx) ?
93123 }
94124 } ,
95125 MetaItemOrLitParser :: Lit ( lit) => match lit. kind {
96126 LitKind :: Bool ( b) => CfgEntry :: Bool ( b, lit. span ) ,
97- _ => return Err ( cx. expected_identifier ( lit. span ) ) ,
127+ _ => return Err ( cx. adcx ( ) . expected_identifier ( lit. span ) ) ,
98128 } ,
99129 } )
100130}
@@ -152,17 +182,17 @@ fn parse_cfg_entry_target<S: Stage>(
152182 for sub_item in list. mixed ( ) {
153183 // First, validate that this is a NameValue item
154184 let Some ( sub_item) = sub_item. meta_item ( ) else {
155- cx. expected_name_value ( sub_item. span ( ) , None ) ;
185+ cx. adcx ( ) . expected_name_value ( sub_item. span ( ) , None ) ;
156186 continue ;
157187 } ;
158188 let Some ( nv) = sub_item. args ( ) . name_value ( ) else {
159- cx. expected_name_value ( sub_item. span ( ) , None ) ;
189+ cx. adcx ( ) . expected_name_value ( sub_item. span ( ) , None ) ;
160190 continue ;
161191 } ;
162192
163193 // Then, parse it as a name-value item
164194 let Some ( name) = sub_item. path ( ) . word_sym ( ) . filter ( |s| !s. is_path_segment_keyword ( ) ) else {
165- return Err ( cx. expected_identifier ( sub_item. path ( ) . span ( ) ) ) ;
195+ return Err ( cx. adcx ( ) . expected_identifier ( sub_item. path ( ) . span ( ) ) ) ;
166196 } ;
167197 let name = Symbol :: intern ( & format ! ( "target_{name}" ) ) ;
168198 if let Ok ( cfg) =
@@ -187,9 +217,9 @@ pub(crate) fn parse_name_value<S: Stage>(
187217 None => None ,
188218 Some ( value) => {
189219 let Some ( value_str) = value. value_as_str ( ) else {
190- return Err (
191- cx . expected_string_literal ( value . value_span , Some ( value . value_as_lit ( ) ) )
192- ) ;
220+ return Err ( cx
221+ . adcx ( )
222+ . expected_string_literal ( value . value_span , Some ( value . value_as_lit ( ) ) ) ) ;
193223 } ;
194224 Some ( ( value_str, value. value_span ) )
195225 }
@@ -335,8 +365,10 @@ pub fn parse_cfg_attr(
335365 path : AttrPath :: from_ast ( & cfg_attr. get_normal_item ( ) . path , identity) ,
336366 description : ParsedDescription :: Attribute ,
337367 reason,
338- suggestions : CFG_ATTR_TEMPLATE
339- . suggestions ( AttrSuggestionStyle :: Attribute ( cfg_attr. style ) , sym:: cfg_attr) ,
368+ suggestions : session_diagnostics:: AttributeParseErrorSuggestions :: CreatedByTemplate (
369+ CFG_ATTR_TEMPLATE
370+ . suggestions ( AttrSuggestionStyle :: Attribute ( cfg_attr. style ) , sym:: cfg_attr) ,
371+ ) ,
340372 } ) ;
341373 }
342374 }
0 commit comments