@@ -5,49 +5,11 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
55use rustc_errors:: { add_elided_lifetime_in_path_suggestion, Diag } ;
66use rustc_errors:: { Applicability , SuggestionStyle } ;
77use rustc_middle:: middle:: stability;
8- use rustc_session:: config:: ExpectedValues ;
98use rustc_session:: lint:: BuiltinLintDiag ;
109use rustc_session:: Session ;
11- use rustc_span:: edit_distance:: find_best_match_for_name;
12- use rustc_span:: symbol:: { sym, Symbol } ;
1310use rustc_span:: BytePos ;
1411
15- const MAX_CHECK_CFG_NAMES_OR_VALUES : usize = 35 ;
16-
17- fn check_cfg_expected_note (
18- sess : & Session ,
19- possibilities : & [ Symbol ] ,
20- type_ : & str ,
21- name : Option < Symbol > ,
22- suffix : & str ,
23- ) -> String {
24- use std:: fmt:: Write ;
25-
26- let n_possibilities = if sess. opts . unstable_opts . check_cfg_all_expected {
27- possibilities. len ( )
28- } else {
29- std:: cmp:: min ( possibilities. len ( ) , MAX_CHECK_CFG_NAMES_OR_VALUES )
30- } ;
31-
32- let mut possibilities = possibilities. iter ( ) . map ( Symbol :: as_str) . collect :: < Vec < _ > > ( ) ;
33- possibilities. sort ( ) ;
34-
35- let and_more = possibilities. len ( ) . saturating_sub ( n_possibilities) ;
36- let possibilities = possibilities[ ..n_possibilities] . join ( "`, `" ) ;
37-
38- let mut note = String :: with_capacity ( 50 + possibilities. len ( ) ) ;
39-
40- write ! ( & mut note, "expected {type_}" ) . unwrap ( ) ;
41- if let Some ( name) = name {
42- write ! ( & mut note, " for `{name}`" ) . unwrap ( ) ;
43- }
44- write ! ( & mut note, " are: {suffix}`{possibilities}`" ) . unwrap ( ) ;
45- if and_more > 0 {
46- write ! ( & mut note, " and {and_more} more" ) . unwrap ( ) ;
47- }
48-
49- note
50- }
12+ mod check_cfg;
5113
5214pub ( super ) fn builtin ( sess : & Session , diagnostic : BuiltinLintDiag , diag : & mut Diag < ' _ , ( ) > ) {
5315 match diagnostic {
@@ -219,242 +181,11 @@ pub(super) fn builtin(sess: &Session, diagnostic: BuiltinLintDiag, diag: &mut Di
219181 diag. help ( help) ;
220182 diag. note ( "see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information" ) ;
221183 }
222- BuiltinLintDiag :: UnexpectedCfgName ( ( name, name_span) , value) => {
223- #[ allow( rustc:: potential_query_instability) ]
224- let possibilities: Vec < Symbol > =
225- sess. psess . check_config . expecteds . keys ( ) . copied ( ) . collect ( ) ;
226-
227- let mut names_possibilities: Vec < _ > = if value. is_none ( ) {
228- // We later sort and display all the possibilities, so the order here does not matter.
229- #[ allow( rustc:: potential_query_instability) ]
230- sess. psess
231- . check_config
232- . expecteds
233- . iter ( )
234- . filter_map ( |( k, v) | match v {
235- ExpectedValues :: Some ( v) if v. contains ( & Some ( name) ) => Some ( k) ,
236- _ => None ,
237- } )
238- . collect ( )
239- } else {
240- Vec :: new ( )
241- } ;
242-
243- let is_from_cargo = rustc_session:: utils:: was_invoked_from_cargo ( ) ;
244- let mut is_feature_cfg = name == sym:: feature;
245-
246- if is_feature_cfg && is_from_cargo {
247- diag. help ( "consider defining some features in `Cargo.toml`" ) ;
248- // Suggest the most probable if we found one
249- } else if let Some ( best_match) = find_best_match_for_name ( & possibilities, name, None ) {
250- if let Some ( ExpectedValues :: Some ( best_match_values) ) =
251- sess. psess . check_config . expecteds . get ( & best_match)
252- {
253- // We will soon sort, so the initial order does not matter.
254- #[ allow( rustc:: potential_query_instability) ]
255- let mut possibilities =
256- best_match_values. iter ( ) . flatten ( ) . map ( Symbol :: as_str) . collect :: < Vec < _ > > ( ) ;
257- possibilities. sort ( ) ;
258-
259- let mut should_print_possibilities = true ;
260- if let Some ( ( value, value_span) ) = value {
261- if best_match_values. contains ( & Some ( value) ) {
262- diag. span_suggestion (
263- name_span,
264- "there is a config with a similar name and value" ,
265- best_match,
266- Applicability :: MaybeIncorrect ,
267- ) ;
268- should_print_possibilities = false ;
269- } else if best_match_values. contains ( & None ) {
270- diag. span_suggestion (
271- name_span. to ( value_span) ,
272- "there is a config with a similar name and no value" ,
273- best_match,
274- Applicability :: MaybeIncorrect ,
275- ) ;
276- should_print_possibilities = false ;
277- } else if let Some ( first_value) = possibilities. first ( ) {
278- diag. span_suggestion (
279- name_span. to ( value_span) ,
280- "there is a config with a similar name and different values" ,
281- format ! ( "{best_match} = \" {first_value}\" " ) ,
282- Applicability :: MaybeIncorrect ,
283- ) ;
284- } else {
285- diag. span_suggestion (
286- name_span. to ( value_span) ,
287- "there is a config with a similar name and different values" ,
288- best_match,
289- Applicability :: MaybeIncorrect ,
290- ) ;
291- } ;
292- } else {
293- diag. span_suggestion (
294- name_span,
295- "there is a config with a similar name" ,
296- best_match,
297- Applicability :: MaybeIncorrect ,
298- ) ;
299- }
300-
301- if !possibilities. is_empty ( ) && should_print_possibilities {
302- let possibilities = possibilities. join ( "`, `" ) ;
303- diag. help ( format ! (
304- "expected values for `{best_match}` are: `{possibilities}`"
305- ) ) ;
306- }
307- } else {
308- diag. span_suggestion (
309- name_span,
310- "there is a config with a similar name" ,
311- best_match,
312- Applicability :: MaybeIncorrect ,
313- ) ;
314- }
315-
316- is_feature_cfg |= best_match == sym:: feature;
317- } else {
318- if !names_possibilities. is_empty ( ) && names_possibilities. len ( ) <= 3 {
319- names_possibilities. sort ( ) ;
320- for cfg_name in names_possibilities. iter ( ) {
321- diag. span_suggestion (
322- name_span,
323- "found config with similar value" ,
324- format ! ( "{cfg_name} = \" {name}\" " ) ,
325- Applicability :: MaybeIncorrect ,
326- ) ;
327- }
328- }
329- if !possibilities. is_empty ( ) {
330- diag. help_once ( check_cfg_expected_note (
331- sess,
332- & possibilities,
333- "names" ,
334- None ,
335- "" ,
336- ) ) ;
337- }
338- }
339-
340- let inst = if let Some ( ( value, _value_span) ) = value {
341- let pre = if is_from_cargo { "\\ " } else { "" } ;
342- format ! ( "cfg({name}, values({pre}\" {value}{pre}\" ))" )
343- } else {
344- format ! ( "cfg({name})" )
345- } ;
346-
347- if is_from_cargo {
348- if !is_feature_cfg {
349- diag. help ( format ! ( "consider using a Cargo feature instead or adding `println!(\" cargo:rustc-check-cfg={inst}\" );` to the top of a `build.rs`" ) ) ;
350- }
351- diag. note ( "see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration" ) ;
352- } else {
353- diag. help ( format ! ( "to expect this configuration use `--check-cfg={inst}`" ) ) ;
354- diag. note ( "see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration" ) ;
355- }
184+ BuiltinLintDiag :: UnexpectedCfgName ( name, value) => {
185+ check_cfg:: unexpected_cfg_name ( sess, diag, name, value)
356186 }
357- BuiltinLintDiag :: UnexpectedCfgValue ( ( name, name_span) , value) => {
358- let Some ( ExpectedValues :: Some ( values) ) = & sess. psess . check_config . expecteds . get ( & name)
359- else {
360- bug ! (
361- "it shouldn't be possible to have a diagnostic on a value whose name is not in values"
362- ) ;
363- } ;
364- let mut have_none_possibility = false ;
365- // We later sort possibilities if it is not empty, so the
366- // order here does not matter.
367- #[ allow( rustc:: potential_query_instability) ]
368- let possibilities: Vec < Symbol > = values
369- . iter ( )
370- . inspect ( |a| have_none_possibility |= a. is_none ( ) )
371- . copied ( )
372- . flatten ( )
373- . collect ( ) ;
374- let is_from_cargo = rustc_session:: utils:: was_invoked_from_cargo ( ) ;
375-
376- // Show the full list if all possible values for a given name, but don't do it
377- // for names as the possibilities could be very long
378- if !possibilities. is_empty ( ) {
379- diag. note ( check_cfg_expected_note (
380- sess,
381- & possibilities,
382- "values" ,
383- Some ( name) ,
384- if have_none_possibility { "(none), " } else { "" } ,
385- ) ) ;
386-
387- if let Some ( ( value, value_span) ) = value {
388- // Suggest the most probable if we found one
389- if let Some ( best_match) = find_best_match_for_name ( & possibilities, value, None )
390- {
391- diag. span_suggestion (
392- value_span,
393- "there is a expected value with a similar name" ,
394- format ! ( "\" {best_match}\" " ) ,
395- Applicability :: MaybeIncorrect ,
396- ) ;
397- }
398- } else if let & [ first_possibility] = & possibilities[ ..] {
399- diag. span_suggestion (
400- name_span. shrink_to_hi ( ) ,
401- "specify a config value" ,
402- format ! ( " = \" {first_possibility}\" " ) ,
403- Applicability :: MaybeIncorrect ,
404- ) ;
405- }
406- } else if have_none_possibility {
407- diag. note ( format ! ( "no expected value for `{name}`" ) ) ;
408- if let Some ( ( _value, value_span) ) = value {
409- diag. span_suggestion (
410- name_span. shrink_to_hi ( ) . to ( value_span) ,
411- "remove the value" ,
412- "" ,
413- Applicability :: MaybeIncorrect ,
414- ) ;
415- }
416- } else {
417- diag. note ( format ! ( "no expected values for `{name}`" ) ) ;
418-
419- let sp = if let Some ( ( _value, value_span) ) = value {
420- name_span. to ( value_span)
421- } else {
422- name_span
423- } ;
424- diag. span_suggestion ( sp, "remove the condition" , "" , Applicability :: MaybeIncorrect ) ;
425- }
426-
427- // We don't want to suggest adding values to well known names
428- // since those are defined by rustc it-self. Users can still
429- // do it if they want, but should not encourage them.
430- let is_cfg_a_well_know_name = sess. psess . check_config . well_known_names . contains ( & name) ;
431-
432- let inst = if let Some ( ( value, _value_span) ) = value {
433- let pre = if is_from_cargo { "\\ " } else { "" } ;
434- format ! ( "cfg({name}, values({pre}\" {value}{pre}\" ))" )
435- } else {
436- format ! ( "cfg({name})" )
437- } ;
438-
439- if is_from_cargo {
440- if name == sym:: feature {
441- if let Some ( ( value, _value_span) ) = value {
442- diag. help ( format ! (
443- "consider adding `{value}` as a feature in `Cargo.toml`"
444- ) ) ;
445- } else {
446- diag. help ( "consider defining some features in `Cargo.toml`" ) ;
447- }
448- } else if !is_cfg_a_well_know_name {
449- diag. help ( format ! ( "consider using a Cargo feature instead or adding `println!(\" cargo:rustc-check-cfg={inst}\" );` to the top of a `build.rs`" ) ) ;
450- }
451- diag. note ( "see <https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#check-cfg> for more information about checking conditional configuration" ) ;
452- } else {
453- if !is_cfg_a_well_know_name {
454- diag. help ( format ! ( "to expect this configuration use `--check-cfg={inst}`" ) ) ;
455- }
456- diag. note ( "see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration" ) ;
457- }
187+ BuiltinLintDiag :: UnexpectedCfgValue ( name, value) => {
188+ check_cfg:: unexpected_cfg_value ( sess, diag, name, value)
458189 }
459190 BuiltinLintDiag :: DeprecatedWhereclauseLocation ( sugg) => {
460191 let left_sp = diag. span . primary_span ( ) . unwrap ( ) ;
0 commit comments