diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 9a94349e5fde4..789507fb48b52 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 f051fdd11b807..4353a294cc31d 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 df73785b8f635..0767b8dda9b8e 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 1a0fe34352130..bc943f2c09cdf 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 771542cb06fa6..c92a9d04775d1 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, InvalidErrorCode> { + if !self.long_descriptions.contains_key(code) { + return Err(InvalidErrorCode); + } + Ok(self.long_descriptions.get(code).unwrap().clone()) } }