diff --git a/Configurations.md b/Configurations.md
index 669da79087c..72499618755 100644
--- a/Configurations.md
+++ b/Configurations.md
@@ -2180,23 +2180,6 @@ Warns about any comments containing `FIXME` in them when set to `"Always"`. If
 it contains a `#X` (with `X` being a number) in parentheses following the
 `FIXME`, `"Unnumbered"` will ignore it.
 
-See also [`report_todo`](#report_todo).
-
-
-## `report_todo`
-
-Report `TODO` items in comments.
-
-- **Default value**: `"Never"`
-- **Possible values**: `"Always"`, `"Unnumbered"`, `"Never"`
-- **Stable**: No (tracking issue: [#3393](https://github.com/rust-lang/rustfmt/issues/3393))
-
-Warns about any comments containing `TODO` in them when set to `"Always"`. If
-it contains a `#X` (with `X` being a number) in parentheses following the
-`TODO`, `"Unnumbered"` will ignore it.
-
-See also [`report_fixme`](#report_fixme).
-
 ## `required_version`
 
 Require a specific version of rustfmt. If you want to make sure that the
diff --git a/src/config/mod.rs b/src/config/mod.rs
index 18e1854612b..4c14d735689 100644
--- a/src/config/mod.rs
+++ b/src/config/mod.rs
@@ -164,8 +164,6 @@ create_config! {
     error_on_unformatted: bool, false, false,
         "Error if unable to get comments or string literals within max_width, \
          or they are left with trailing whitespaces";
-    report_todo: ReportTactic, ReportTactic::Never, false,
-        "Report all, none or unnumbered occurrences of TODO in source file comments";
     report_fixme: ReportTactic, ReportTactic::Never, false,
         "Report all, none or unnumbered occurrences of FIXME in source file comments";
     ignore: IgnoreList, IgnoreList::default(), false,
@@ -625,7 +623,6 @@ skip_children = false
 hide_parse_errors = false
 error_on_line_overflow = false
 error_on_unformatted = false
-report_todo = "Never"
 report_fixme = "Never"
 ignore = []
 emit_mode = "Files"
diff --git a/src/formatting.rs b/src/formatting.rs
index 281d3e4e808..8e6999643b1 100644
--- a/src/formatting.rs
+++ b/src/formatting.rs
@@ -497,7 +497,7 @@ impl<'a> FormatLines<'a> {
         skipped_range: &'a [(usize, usize)],
         config: &'a Config,
     ) -> FormatLines<'a> {
-        let issue_seeker = BadIssueSeeker::new(config.report_todo(), config.report_fixme());
+        let issue_seeker = BadIssueSeeker::new(config.report_fixme());
         FormatLines {
             name,
             skipped_range,
@@ -537,7 +537,7 @@ impl<'a> FormatLines<'a> {
             }
 
             if self.allow_issue_seek && self.format_line {
-                // Add warnings for bad todos/ fixmes
+                // Add warnings for bad fixmes
                 if let Some(issue) = self.issue_seeker.inspect(c) {
                     self.push_err(ErrorKind::BadIssue(issue), false, false);
                 }
diff --git a/src/issues.rs b/src/issues.rs
index 33fb5522aea..3c39d813a6f 100644
--- a/src/issues.rs
+++ b/src/issues.rs
@@ -6,7 +6,6 @@ use std::fmt;
 
 use crate::config::ReportTactic;
 
-const TO_DO_CHARS: &[char] = &['t', 'o', 'd', 'o'];
 const FIX_ME_CHARS: &[char] = &['f', 'i', 'x', 'm', 'e'];
 
 // Enabled implementation detail is here because it is
@@ -17,7 +16,7 @@ fn is_enabled(report_tactic: ReportTactic) -> bool {
 
 #[derive(Clone, Copy)]
 enum Seeking {
-    Issue { todo_idx: usize, fixme_idx: usize },
+    Issue { fixme_idx: usize },
     Number { issue: Issue, part: NumberPart },
 }
 
@@ -40,7 +39,6 @@ pub struct Issue {
 impl fmt::Display for Issue {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
         let msg = match self.issue_type {
-            IssueType::Todo => "TODO",
             IssueType::Fixme => "FIXME",
         };
         let details = if self.missing_number {
@@ -55,7 +53,6 @@ impl fmt::Display for Issue {
 
 #[derive(PartialEq, Eq, Debug, Clone, Copy)]
 enum IssueType {
-    Todo,
     Fixme,
 }
 
@@ -67,35 +64,27 @@ enum IssueClassification {
 
 pub(crate) struct BadIssueSeeker {
     state: Seeking,
-    report_todo: ReportTactic,
     report_fixme: ReportTactic,
 }
 
 impl BadIssueSeeker {
-    pub(crate) fn new(report_todo: ReportTactic, report_fixme: ReportTactic) -> BadIssueSeeker {
+    pub(crate) fn new(report_fixme: ReportTactic) -> BadIssueSeeker {
         BadIssueSeeker {
-            state: Seeking::Issue {
-                todo_idx: 0,
-                fixme_idx: 0,
-            },
-            report_todo,
+            state: Seeking::Issue { fixme_idx: 0 },
             report_fixme,
         }
     }
 
     pub(crate) fn is_disabled(&self) -> bool {
-        !is_enabled(self.report_todo) && !is_enabled(self.report_fixme)
+        !is_enabled(self.report_fixme)
     }
 
     // Check whether or not the current char is conclusive evidence for an
     // unnumbered TO-DO or FIX-ME.
     pub(crate) fn inspect(&mut self, c: char) -> Option<Issue> {
         match self.state {
-            Seeking::Issue {
-                todo_idx,
-                fixme_idx,
-            } => {
-                self.state = self.inspect_issue(c, todo_idx, fixme_idx);
+            Seeking::Issue { fixme_idx } => {
+                self.state = self.inspect_issue(c, fixme_idx);
             }
             Seeking::Number { issue, part } => {
                 let result = self.inspect_number(c, issue, part);
@@ -104,10 +93,7 @@ impl BadIssueSeeker {
                     return None;
                 }
 
-                self.state = Seeking::Issue {
-                    todo_idx: 0,
-                    fixme_idx: 0,
-                };
+                self.state = Seeking::Issue { fixme_idx: 0 };
 
                 if let IssueClassification::Bad(issue) = result {
                     return Some(issue);
@@ -118,21 +104,9 @@ impl BadIssueSeeker {
         None
     }
 
-    fn inspect_issue(&mut self, c: char, mut todo_idx: usize, mut fixme_idx: usize) -> Seeking {
+    fn inspect_issue(&mut self, c: char, mut fixme_idx: usize) -> Seeking {
         if let Some(lower_case_c) = c.to_lowercase().next() {
-            if is_enabled(self.report_todo) && lower_case_c == TO_DO_CHARS[todo_idx] {
-                todo_idx += 1;
-                if todo_idx == TO_DO_CHARS.len() {
-                    return Seeking::Number {
-                        issue: Issue {
-                            issue_type: IssueType::Todo,
-                            missing_number: matches!(self.report_todo, ReportTactic::Unnumbered),
-                        },
-                        part: NumberPart::OpenParen,
-                    };
-                }
-                fixme_idx = 0;
-            } else if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] {
+            if is_enabled(self.report_fixme) && lower_case_c == FIX_ME_CHARS[fixme_idx] {
                 // Exploit the fact that the character sets of todo and fixme
                 // are disjoint by adding else.
                 fixme_idx += 1;
@@ -145,17 +119,12 @@ impl BadIssueSeeker {
                         part: NumberPart::OpenParen,
                     };
                 }
-                todo_idx = 0;
             } else {
-                todo_idx = 0;
                 fixme_idx = 0;
             }
         }
 
-        Seeking::Issue {
-            todo_idx,
-            fixme_idx,
-        }
+        Seeking::Issue { fixme_idx }
     }
 
     fn inspect_number(
@@ -206,7 +175,7 @@ impl BadIssueSeeker {
 #[test]
 fn find_unnumbered_issue() {
     fn check_fail(text: &str, failing_pos: usize) {
-        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
+        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered);
         assert_eq!(
             Some(failing_pos),
             text.find(|c| seeker.inspect(c).is_some())
@@ -214,12 +183,10 @@ fn find_unnumbered_issue() {
     }
 
     fn check_pass(text: &str) {
-        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered, ReportTactic::Unnumbered);
+        let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered);
         assert_eq!(None, text.find(|c| seeker.inspect(c).is_some()));
     }
 
-    check_fail("TODO\n", 4);
-    check_pass(" TO FIX DOME\n");
     check_fail(" \n FIXME\n", 8);
     check_fail("FIXME(\n", 6);
     check_fail("FIXME(#\n", 7);
@@ -228,71 +195,28 @@ fn find_unnumbered_issue() {
     check_pass("FIXME(#1222)\n");
     check_fail("FIXME(#12\n22)\n", 9);
     check_pass("FIXME(@maintainer, #1222, hello)\n");
-    check_fail("TODO(#22) FIXME\n", 15);
 }
 
 #[test]
 fn find_issue() {
-    fn is_bad_issue(text: &str, report_todo: ReportTactic, report_fixme: ReportTactic) -> bool {
-        let mut seeker = BadIssueSeeker::new(report_todo, report_fixme);
+    fn is_bad_issue(text: &str, report_fixme: ReportTactic) -> bool {
+        let mut seeker = BadIssueSeeker::new(report_fixme);
         text.chars().any(|c| seeker.inspect(c).is_some())
     }
 
-    assert!(is_bad_issue(
-        "TODO(@maintainer, #1222, hello)\n",
-        ReportTactic::Always,
-        ReportTactic::Never,
-    ));
-
-    assert!(!is_bad_issue(
-        "TODO: no number\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
-
-    assert!(!is_bad_issue(
-        "Todo: mixed case\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
-
-    assert!(is_bad_issue(
-        "This is a FIXME(#1)\n",
-        ReportTactic::Never,
-        ReportTactic::Always,
-    ));
+    assert!(is_bad_issue("This is a FIXME(#1)\n", ReportTactic::Always));
 
     assert!(is_bad_issue(
         "This is a FixMe(#1) mixed case\n",
-        ReportTactic::Never,
         ReportTactic::Always,
     ));
 
-    assert!(!is_bad_issue(
-        "bad FIXME\n",
-        ReportTactic::Always,
-        ReportTactic::Never,
-    ));
+    assert!(!is_bad_issue("bad FIXME\n", ReportTactic::Never));
 }
 
 #[test]
 fn issue_type() {
-    let mut seeker = BadIssueSeeker::new(ReportTactic::Always, ReportTactic::Never);
-    let expected = Some(Issue {
-        issue_type: IssueType::Todo,
-        missing_number: false,
-    });
-
-    assert_eq!(
-        expected,
-        "TODO(#100): more awesomeness"
-            .chars()
-            .map(|c| seeker.inspect(c))
-            .find(Option::is_some)
-            .unwrap()
-    );
-
-    let mut seeker = BadIssueSeeker::new(ReportTactic::Never, ReportTactic::Unnumbered);
+    let mut seeker = BadIssueSeeker::new(ReportTactic::Unnumbered);
     let expected = Some(Issue {
         issue_type: IssueType::Fixme,
         missing_number: true,
diff --git a/src/test/mod.rs b/src/test/mod.rs
index 4bad8e71481..0eda9e4b116 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -9,7 +9,7 @@ use std::process::{Command, Stdio};
 use std::str::Chars;
 use std::thread;
 
-use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle, ReportTactic};
+use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle};
 use crate::formatting::{ReportedErrors, SourceFile};
 use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter};
 use crate::source_file;
@@ -688,9 +688,6 @@ fn read_config(filename: &Path) -> Config {
         }
     }
 
-    // Don't generate warnings for to-do items.
-    config.set().report_todo(ReportTactic::Never);
-
     config
 }
 
diff --git a/tests/config/small_tabs.toml b/tests/config/small_tabs.toml
index 35c8fd86467..598edda6abe 100644
--- a/tests/config/small_tabs.toml
+++ b/tests/config/small_tabs.toml
@@ -6,7 +6,6 @@ brace_style = "SameLineWhere"
 fn_args_layout = "Tall"
 trailing_comma = "Vertical"
 indent_style = "Block"
-report_todo = "Always"
 report_fixme = "Never"
 reorder_imports = false
 format_strings = true