diff --git a/Cargo.lock b/Cargo.lock
index a226a10f89d4..9e5deedb66ff 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1445,6 +1445,7 @@ name = "error_index_generator"
 version = "0.0.0"
 dependencies = [
  "mdbook",
+ "rustc_error_codes",
 ]
 
 [[package]]
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 54bcb154da28..464ddae476a5 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -485,7 +485,7 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
     let normalised =
         if upper_cased_code.starts_with('E') { upper_cased_code } else { format!("E{code:0>4}") };
     match registry.try_find_description(&normalised) {
-        Ok(Some(description)) => {
+        Ok(description) => {
             let mut is_in_code_block = false;
             let mut text = String::new();
             // Slice off the leading newline and print.
@@ -509,9 +509,6 @@ fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) {
                 print!("{text}");
             }
         }
-        Ok(None) => {
-            early_error(output, &format!("no extended information for {code}"));
-        }
         Err(InvalidErrorCode) => {
             early_error(output, &format!("{code} is not a valid error code"));
         }
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 97201219cdf6..df857be85ada 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -513,7 +513,9 @@ E0790: include_str!("./error_codes/E0790.md"),
 E0791: include_str!("./error_codes/E0791.md"),
 E0792: include_str!("./error_codes/E0792.md"),
 E0793: include_str!("./error_codes/E0793.md"),
-;
+}
+
+// Undocumented removed error codes. Note that many removed error codes are documented.
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
 //  E0019, // merged into E0015
@@ -570,7 +572,7 @@ E0793: include_str!("./error_codes/E0793.md"),
 //  E0246, // invalid recursive type
 //  E0247,
 //  E0248, // value used as a type, now reported earlier during resolution
-           // as E0412
+//         // as E0412
 //  E0249,
 //  E0257,
 //  E0258,
@@ -631,14 +633,14 @@ E0793: include_str!("./error_codes/E0793.md"),
 //  E0558, // replaced with a generic attribute input check
 //  E0563, // cannot determine a type for this `impl Trait` removed in 6383de15
 //  E0564, // only named lifetimes are allowed in `impl Trait`,
-           // but `{}` was found in the type `{}`
+//         // but `{}` was found in the type `{}`
 //  E0598, // lifetime of {} is too short to guarantee its contents can be...
 //  E0611, // merged into E0616
 //  E0612, // merged into E0609
 //  E0613, // Removed (merged with E0609)
 //  E0629, // missing 'feature' (rustc_const_unstable)
 //  E0630, // rustc_const_unstable attribute must be paired with stable/unstable
-           // attribute
+//         // attribute
 //  E0645, // trait aliases not finished
 //  E0694, // an unknown tool name found in scoped attributes
 //  E0702, // replaced with a generic attribute input check
@@ -647,4 +649,3 @@ E0793: include_str!("./error_codes/E0793.md"),
 //  E0721, // `await` keyword
 //  E0723, // unstable feature in `const` context
 //  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
-}
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index bd424dd9d068..d6b120e4dfcf 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -5,10 +5,9 @@
 //! the goal being to make their maintenance easier.
 
 macro_rules! register_diagnostics {
-    ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
-        pub static DIAGNOSTICS: &[(&str, Option<&str>)] = &[
-            $( (stringify!($ecode), Some($message)), )*
-            $( (stringify!($code), None), )*
+    ($($ecode:ident: $message:expr,)*) => (
+        pub static DIAGNOSTICS: &[(&str, &str)] = &[
+            $( (stringify!($ecode), $message), )*
         ];
     )
 }
diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs
index e475fc725c33..f32d6b96b9b2 100644
--- a/compiler/rustc_errors/src/json.rs
+++ b/compiler/rustc_errors/src/json.rs
@@ -580,7 +580,7 @@ impl DiagnosticCode {
             let je_result =
                 je.registry.as_ref().map(|registry| registry.try_find_description(&s)).unwrap();
 
-            DiagnosticCode { code: s, explanation: je_result.unwrap_or(None) }
+            DiagnosticCode { code: s, explanation: je_result.ok() }
         })
     }
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index edec8cce92f9..c71668657f7f 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -1477,9 +1477,7 @@ impl HandlerInner {
                 .emitted_diagnostic_codes
                 .iter()
                 .filter_map(|x| match &x {
-                    DiagnosticId::Error(s)
-                        if registry.try_find_description(s).map_or(false, |o| o.is_some()) =>
-                    {
+                    DiagnosticId::Error(s) if registry.try_find_description(s).is_ok() => {
                         Some(s.clone())
                     }
                     _ => None,
diff --git a/compiler/rustc_errors/src/registry.rs b/compiler/rustc_errors/src/registry.rs
index da764d993bbd..f26d8e7ebdc3 100644
--- a/compiler/rustc_errors/src/registry.rs
+++ b/compiler/rustc_errors/src/registry.rs
@@ -5,21 +5,17 @@ pub struct InvalidErrorCode;
 
 #[derive(Clone)]
 pub struct Registry {
-    long_descriptions: FxHashMap<&'static str, Option<&'static str>>,
+    long_descriptions: FxHashMap<&'static str, &'static str>,
 }
 
 impl Registry {
-    pub fn new(long_descriptions: &[(&'static str, Option<&'static str>)]) -> Registry {
+    pub fn new(long_descriptions: &[(&'static str, &'static str)]) -> Registry {
         Registry { long_descriptions: long_descriptions.iter().copied().collect() }
     }
 
     /// 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> {
+    /// registry.
+    pub fn try_find_description(&self, code: &str) -> Result<&'static str, InvalidErrorCode> {
         self.long_descriptions.get(code).copied().ok_or(InvalidErrorCode)
     }
 }
diff --git a/src/tools/error_index_generator/Cargo.toml b/src/tools/error_index_generator/Cargo.toml
index f4dac6e947e3..76c2e330b210 100644
--- a/src/tools/error_index_generator/Cargo.toml
+++ b/src/tools/error_index_generator/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 mdbook = { version = "0.4", default-features = false, features = ["search"] }
+rustc_error_codes = { version = "0.0.0", path = "../../../compiler/rustc_error_codes" }
 
 [[bin]]
 name = "error_index_generator"
diff --git a/src/tools/error_index_generator/main.rs b/src/tools/error_index_generator/main.rs
index 373196b66428..f984275b164c 100644
--- a/src/tools/error_index_generator/main.rs
+++ b/src/tools/error_index_generator/main.rs
@@ -2,9 +2,6 @@
 
 extern crate rustc_driver;
 
-// We use the function we generate from `register_diagnostics!`.
-use crate::error_codes::error_codes;
-
 use std::env;
 use std::error::Error;
 use std::fs::{self, File};
@@ -17,22 +14,6 @@ use std::str::FromStr;
 use mdbook::book::{parse_summary, BookItem, Chapter};
 use mdbook::{Config, MDBook};
 
-macro_rules! register_diagnostics {
-    ($($error_code:ident: $message:expr,)+ ; $($undocumented:ident,)* ) => {
-        pub fn error_codes() -> Vec<(&'static str, Option<&'static str>)> {
-            let mut errors: Vec<(&str, Option<&str>)> = vec![
-                $((stringify!($error_code), Some($message)),)+
-                $((stringify!($undocumented), None),)*
-            ];
-            errors.sort();
-            errors
-        }
-    }
-}
-
-#[path = "../../../compiler/rustc_error_codes/src/error_codes.rs"]
-mod error_codes;
-
 enum OutputFormat {
     HTML,
     Markdown,
@@ -55,11 +36,8 @@ fn render_markdown(output_path: &Path) -> Result<(), Box<dyn Error>> {
 
     write!(output_file, "# Rust Compiler Error Index\n")?;
 
-    for (err_code, description) in error_codes().iter() {
-        match description {
-            Some(ref desc) => write!(output_file, "## {}\n{}\n", err_code, desc)?,
-            None => {}
-        }
+    for (err_code, description) in rustc_error_codes::DIAGNOSTICS.iter() {
+        write!(output_file, "## {}\n{}\n", err_code, description)?
     }
 
     Ok(())
@@ -105,27 +83,23 @@ This page lists all the error codes emitted by the Rust compiler.
 "
     );
 
-    let err_codes = error_codes();
+    let err_codes = rustc_error_codes::DIAGNOSTICS;
     let mut chapters = Vec::with_capacity(err_codes.len());
 
     for (err_code, explanation) in err_codes.iter() {
-        if let Some(explanation) = explanation {
-            introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
-
-            let content = add_rust_attribute_on_codeblock(explanation);
-            chapters.push(BookItem::Chapter(Chapter {
-                name: err_code.to_string(),
-                content: format!("# Error code {}\n\n{}\n", err_code, content),
-                number: None,
-                sub_items: Vec::new(),
-                // We generate it into the `error_codes` folder.
-                path: Some(PathBuf::from(&format!("{}.html", err_code))),
-                source_path: None,
-                parent_names: Vec::new(),
-            }));
-        } else {
-            introduction.push_str(&format!(" * {}\n", err_code));
-        }
+        introduction.push_str(&format!(" * [{0}](./{0}.html)\n", err_code));
+
+        let content = add_rust_attribute_on_codeblock(explanation);
+        chapters.push(BookItem::Chapter(Chapter {
+            name: err_code.to_string(),
+            content: format!("# Error code {}\n\n{}\n", err_code, content),
+            number: None,
+            sub_items: Vec::new(),
+            // We generate it into the `error_codes` folder.
+            path: Some(PathBuf::from(&format!("{}.html", err_code))),
+            source_path: None,
+            parent_names: Vec::new(),
+        }));
     }
 
     let mut config = Config::from_str(include_str!("book_config.toml"))?;
diff --git a/src/tools/tidy/src/error_codes.rs b/src/tools/tidy/src/error_codes.rs
index 8c904e8d7123..c60caa0d49c6 100644
--- a/src/tools/tidy/src/error_codes.rs
+++ b/src/tools/tidy/src/error_codes.rs
@@ -45,7 +45,7 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
     let mut errors = Vec::new();
 
     // Stage 1: create list
-    let error_codes = extract_error_codes(root_path, &mut errors, verbose);
+    let error_codes = extract_error_codes(root_path, &mut errors);
     println!("Found {} error codes", error_codes.len());
     println!("Highest error code: `{}`", error_codes.iter().max().unwrap());
 
@@ -65,18 +65,17 @@ pub fn check(root_path: &Path, search_paths: &[&Path], verbose: bool, bad: &mut
 }
 
 /// Stage 1: Parses a list of error codes from `error_codes.rs`.
-fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool) -> Vec<String> {
+fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>) -> Vec<String> {
     let path = root_path.join(Path::new(ERROR_CODES_PATH));
     let file =
         fs::read_to_string(&path).unwrap_or_else(|e| panic!("failed to read `{path:?}`: {e}"));
 
     let mut error_codes = Vec::new();
-    let mut reached_undocumented_codes = false;
 
     for line in file.lines() {
         let line = line.trim();
 
-        if !reached_undocumented_codes && line.starts_with('E') {
+        if line.starts_with('E') {
             let split_line = line.split_once(':');
 
             // Extract the error code from the line, emitting a fatal error if it is not in a correct format.
@@ -111,23 +110,6 @@ fn extract_error_codes(root_path: &Path, errors: &mut Vec<String>, verbose: bool
             }
 
             error_codes.push(err_code);
-        } else if reached_undocumented_codes && line.starts_with('E') {
-            let err_code = match line.split_once(',') {
-                None => line,
-                Some((err_code, _)) => err_code,
-            }
-            .to_string();
-
-            verbose_print!(verbose, "warning: Error code `{}` is undocumented.", err_code);
-
-            if error_codes.contains(&err_code) {
-                errors.push(format!("Found duplicate error code: `{}`", err_code));
-            }
-
-            error_codes.push(err_code);
-        } else if line == ";" {
-            // Once we reach the undocumented error codes, adapt to different syntax.
-            reached_undocumented_codes = true;
         }
     }