about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-03-02 03:16:22 +0000
committerbors <bors@rust-lang.org>2020-03-02 03:16:22 +0000
commite86c9e6ef8be7ddec0360f20aae7d86c69c59a83 (patch)
tree82d8856872d01ee573207ec3ac37de93eb5fd6e5
parent9dc8dad14fc31f49254d299457e34d00721c4a73 (diff)
parent5f3ffee6b77f073b78bdc76e7a0f4811bc39e7f9 (diff)
downloadrust-e86c9e6ef8be7ddec0360f20aae7d86c69c59a83.tar.gz
rust-e86c9e6ef8be7ddec0360f20aae7d86c69c59a83.zip
Auto merge of #69442 - jakevossen5:master, r=Mark-Simulacrum
`--explain` disambiguates no long description and invalid error codes

Closes #44710

First code contribution here, so feedback is very much appreciated!

cc @zackmdavis
cc @Mark-Simulacrum
-rw-r--r--src/librustc_driver/lib.rs16
-rw-r--r--src/librustc_error_codes/lib.rs5
-rw-r--r--src/librustc_errors/json.rs6
-rw-r--r--src/librustc_errors/lib.rs8
-rw-r--r--src/librustc_errors/registry.rs24
5 files changed, 42 insertions, 17 deletions
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 9a94349e5fd..789507fb48b 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -30,7 +30,10 @@ use rustc_codegen_ssa::CodegenResults;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
 use rustc_data_structures::profiling::print_time_passes_entry;
 use rustc_data_structures::sync::SeqCst;
-use rustc_errors::{registry::Registry, PResult};
+use rustc_errors::{
+    registry::{InvalidErrorCode, Registry},
+    PResult,
+};
 use rustc_feature::{find_gated_cfg, UnstableFeatures};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_interface::util::{collect_crate_types, get_builtin_codegen_backend};
@@ -522,11 +525,10 @@ fn stdout_isatty() -> bool {
 fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
     let normalised =
         if code.starts_with('E') { code.to_string() } else { format!("E{0:0>4}", code) };
-    match registry.find_description(&normalised) {
-        Some(ref description) => {
+    match registry.try_find_description(&normalised) {
+        Ok(Some(description)) => {
             let mut is_in_code_block = false;
             let mut text = String::new();
-
             // Slice off the leading newline and print.
             for line in description.lines() {
                 let indent_level =
@@ -542,16 +544,18 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
                 }
                 text.push('\n');
             }
-
             if stdout_isatty() {
                 show_content_with_pager(&text);
             } else {
                 print!("{}", text);
             }
         }
-        None => {
+        Ok(None) => {
             early_error(output, &format!("no extended information for {}", code));
         }
+        Err(InvalidErrorCode) => {
+            early_error(output, &format!("{} is not a valid error code", code));
+        }
     }
 }
 
diff --git a/src/librustc_error_codes/lib.rs b/src/librustc_error_codes/lib.rs
index f051fdd11b8..4353a294cc3 100644
--- a/src/librustc_error_codes/lib.rs
+++ b/src/librustc_error_codes/lib.rs
@@ -3,8 +3,9 @@
 
 macro_rules! register_diagnostics {
     ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
-        pub static DIAGNOSTICS: &[(&str, &str)] = &[
-            $( (stringify!($ecode), $message), )*
+        pub static DIAGNOSTICS: &[(&str, Option<&str>)] = &[
+            $( (stringify!($ecode), Some($message)), )*
+            $( (stringify!($code), None), )*
         ];
     )
 }
diff --git a/src/librustc_errors/json.rs b/src/librustc_errors/json.rs
index df73785b8f6..0767b8dda9b 100644
--- a/src/librustc_errors/json.rs
+++ b/src/librustc_errors/json.rs
@@ -419,10 +419,10 @@ impl DiagnosticCode {
                 DiagnosticId::Error(s) => s,
                 DiagnosticId::Lint(s) => s,
             };
-            let explanation =
-                je.registry.as_ref().and_then(|registry| registry.find_description(&s));
+            let je_result =
+                je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
 
-            DiagnosticCode { code: s, explanation }
+            DiagnosticCode { code: s, explanation: je_result.unwrap_or(None) }
         })
     }
 }
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 1a0fe343521..bc943f2c09c 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -786,8 +786,12 @@ impl HandlerInner {
                 .emitted_diagnostic_codes
                 .iter()
                 .filter_map(|x| match &x {
-                    DiagnosticId::Error(s) if registry.find_description(s).is_some() => {
-                        Some(s.clone())
+                    DiagnosticId::Error(s) => {
+                        if let Ok(Some(_explanation)) = registry.try_find_description(s) {
+                            Some(s.clone())
+                        } else {
+                            None
+                        }
                     }
                     _ => None,
                 })
diff --git a/src/librustc_errors/registry.rs b/src/librustc_errors/registry.rs
index 771542cb06f..c92a9d04775 100644
--- a/src/librustc_errors/registry.rs
+++ b/src/librustc_errors/registry.rs
@@ -1,16 +1,32 @@
 use rustc_data_structures::fx::FxHashMap;
 
+#[derive(Debug)]
+pub struct InvalidErrorCode;
+
 #[derive(Clone)]
 pub struct Registry {
-    descriptions: FxHashMap<&'static str, &'static str>,
+    long_descriptions: FxHashMap<&'static str, Option<&'static str>>,
 }
 
 impl Registry {
-    pub fn new(descriptions: &[(&'static str, &'static str)]) -> Registry {
-        Registry { descriptions: descriptions.iter().cloned().collect() }
+    pub fn new(long_descriptions: &[(&'static str, Option<&'static str>)]) -> Registry {
+        Registry { long_descriptions: long_descriptions.iter().cloned().collect() }
     }
 
+    /// This will panic if an invalid error code is passed in
     pub fn find_description(&self, code: &str) -> Option<&'static str> {
-        self.descriptions.get(code).cloned()
+        self.try_find_description(code).unwrap()
+    }
+    /// Returns `InvalidErrorCode` if the code requested does not exist in the
+    /// registry. Otherwise, returns an `Option` where `None` means the error
+    /// code is valid but has no extended information.
+    pub fn try_find_description(
+        &self,
+        code: &str,
+    ) -> Result<Option<&'static str>, InvalidErrorCode> {
+        if !self.long_descriptions.contains_key(code) {
+            return Err(InvalidErrorCode);
+        }
+        Ok(self.long_descriptions.get(code).unwrap().clone())
     }
 }