about summary refs log tree commit diff
path: root/compiler/rustc_interface/src/interface.rs
diff options
context:
space:
mode:
authorUrgau <urgau@numericable.fr>2024-05-03 21:14:42 +0200
committerUrgau <urgau@numericable.fr>2024-05-06 07:44:41 +0200
commit228496e4f5f7b94d69ec7e5bc858370ce9540fca (patch)
treebe31bf99950a9d0d1ec90a617f3f39b9569173b7 /compiler/rustc_interface/src/interface.rs
parent0b418f2b03fdd146a6099ea8032ea8580d2edf49 (diff)
downloadrust-228496e4f5f7b94d69ec7e5bc858370ce9540fca.tar.gz
rust-228496e4f5f7b94d69ec7e5bc858370ce9540fca.zip
Improve check-cfg CLI errors with more structured diagnostics
Diffstat (limited to 'compiler/rustc_interface/src/interface.rs')
-rw-r--r--compiler/rustc_interface/src/interface.rs51
1 files changed, 41 insertions, 10 deletions
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index c5b81dbd679..55304bbbd92 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -120,14 +120,45 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
         );
         let filename = FileName::cfg_spec_source_code(&s);
 
+        const VISIT: &str =
+            "visit <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more details";
+
         macro_rules! error {
             ($reason:expr) => {
                 #[allow(rustc::untranslatable_diagnostic)]
                 #[allow(rustc::diagnostic_outside_of_impl)]
-                dcx.fatal(format!(
-                    concat!("invalid `--check-cfg` argument: `{}` (", $reason, ")"),
-                    s
-                ))
+                {
+                    let mut diag =
+                        dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
+                    diag.note($reason);
+                    diag.note(VISIT);
+                    diag.emit()
+                }
+            };
+            (in $arg:expr, $reason:expr) => {
+                #[allow(rustc::untranslatable_diagnostic)]
+                #[allow(rustc::diagnostic_outside_of_impl)]
+                {
+                    let mut diag =
+                        dcx.struct_fatal(format!("invalid `--check-cfg` argument: `{s}`"));
+
+                    let pparg = rustc_ast_pretty::pprust::meta_list_item_to_string($arg);
+                    if let Some(lit) = $arg.lit() {
+                        let (lit_kind_article, lit_kind_descr) = {
+                            let lit_kind = lit.as_token_lit().kind;
+                            (lit_kind.article(), lit_kind.descr())
+                        };
+                        diag.note(format!(
+                            "`{pparg}` is {lit_kind_article} {lit_kind_descr} literal"
+                        ));
+                    } else {
+                        diag.note(format!("`{pparg}` is invalid"));
+                    }
+
+                    diag.note($reason);
+                    diag.note(VISIT);
+                    diag.emit()
+                }
             };
         }
 
@@ -183,7 +214,7 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
                 }
                 any_specified = true;
                 if !args.is_empty() {
-                    error!("`any()` must be empty");
+                    error!(in arg, "`any()` takes no argument");
                 }
             } else if arg.has_name(sym::values)
                 && let Some(args) = arg.meta_item_list()
@@ -202,25 +233,25 @@ pub(crate) fn parse_check_cfg(dcx: &DiagCtxt, specs: Vec<String>) -> CheckCfg {
                         && let Some(args) = arg.meta_item_list()
                     {
                         if values_any_specified {
-                            error!("`any()` in `values()` cannot be specified multiple times");
+                            error!(in arg, "`any()` in `values()` cannot be specified multiple times");
                         }
                         values_any_specified = true;
                         if !args.is_empty() {
-                            error!("`any()` must be empty");
+                            error!(in arg, "`any()` in `values()` takes no argument");
                         }
                     } else if arg.has_name(sym::none)
                         && let Some(args) = arg.meta_item_list()
                     {
                         values.insert(None);
                         if !args.is_empty() {
-                            error!("`none()` must be empty");
+                            error!(in arg, "`none()` in `values()` takes no argument");
                         }
                     } else {
-                        error!("`values()` arguments must be string literals, `none()` or `any()`");
+                        error!(in arg, "`values()` arguments must be string literals, `none()` or `any()`");
                     }
                 }
             } else {
-                error!("`cfg()` arguments must be simple identifiers, `any()` or `values(...)`");
+                error!(in arg, "`cfg()` arguments must be simple identifiers, `any()` or `values(...)`");
             }
         }