about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-10-31 14:52:56 +0530
committerGitHub <noreply@github.com>2022-10-31 14:52:56 +0530
commitc1c2922aa1aad541778dfd5a9f8167f9c4d17481 (patch)
treefcf35cc5025b8002b514384290e82ce00fb2c3e3
parent5ee0fb1c688c38a9c2649104ca28e442f0698be3 (diff)
parent88d71504dd7a5d790e9c6ff7a91fcbd82e3aef14 (diff)
downloadrust-c1c2922aa1aad541778dfd5a9f8167f9c4d17481.tar.gz
rust-c1c2922aa1aad541778dfd5a9f8167f9c4d17481.zip
Rollup merge of #103603 - camsteffen:refactor-lang, r=oli-obk
Lang item cleanups

Various cleanups related to lang items.
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs13
-rw-r--r--compiler/rustc_const_eval/src/util/call_kind.rs20
-rw-r--r--compiler/rustc_error_messages/locales/en-US/monomorphize.ftl3
-rw-r--r--compiler/rustc_hir/src/lang_items.rs207
-rw-r--r--compiler/rustc_hir/src/lib.rs2
-rw-r--r--compiler/rustc_hir/src/weak_lang_items.rs60
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs15
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs19
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs6
-rw-r--r--compiler/rustc_middle/src/middle/lang_items.rs4
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/context.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs11
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs6
-rw-r--r--compiler/rustc_passes/src/lang_items.rs32
-rw-r--r--compiler/rustc_passes/src/reachable.rs8
-rw-r--r--compiler/rustc_passes/src/weak_lang_items.rs12
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/lifetimes.rs15
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/unused_peekable.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs6
34 files changed, 225 insertions, 283 deletions
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 84b89cd71a6..a92087305b8 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -22,7 +22,6 @@ use rustc_data_structures::sync::ParallelIterator;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_hir::lang_items::LangItem;
-use rustc_hir::weak_lang_items::WEAK_ITEMS_SYMBOLS;
 use rustc_index::vec::Idx;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
@@ -887,14 +886,14 @@ impl CrateInfo {
         // by the compiler, but that's ok because all this stuff is unstable anyway.
         let target = &tcx.sess.target;
         if !are_upstream_rust_objects_already_included(tcx.sess) {
-            let missing_weak_lang_items: FxHashSet<&Symbol> = info
+            let missing_weak_lang_items: FxHashSet<Symbol> = info
                 .used_crates
                 .iter()
-                .flat_map(|cnum| {
-                    tcx.missing_lang_items(*cnum)
-                        .iter()
-                        .filter(|l| lang_items::required(tcx, **l))
-                        .filter_map(|item| WEAK_ITEMS_SYMBOLS.get(item))
+                .flat_map(|&cnum| tcx.missing_lang_items(cnum))
+                .filter(|l| l.is_weak())
+                .filter_map(|&l| {
+                    let name = l.link_name()?;
+                    lang_items::required(tcx, l).then_some(name)
                 })
                 .collect();
             let prefix = if target.is_like_windows && target.arch == "x86" { "_" } else { "" };
diff --git a/compiler/rustc_const_eval/src/util/call_kind.rs b/compiler/rustc_const_eval/src/util/call_kind.rs
index af9d83f0609..5446ccb1a47 100644
--- a/compiler/rustc_const_eval/src/util/call_kind.rs
+++ b/compiler/rustc_const_eval/src/util/call_kind.rs
@@ -3,7 +3,7 @@
 //! context.
 
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::LangItemGroup;
+use rustc_hir::lang_items;
 use rustc_middle::ty::subst::SubstsRef;
 use rustc_middle::ty::{self, AssocItemContainer, DefIdTree, Instance, ParamEnv, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
@@ -74,22 +74,24 @@ pub fn call_kind<'tcx>(
         }
     });
 
-    let fn_call = parent
-        .and_then(|p| tcx.lang_items().group(LangItemGroup::Fn).iter().find(|did| **did == p));
+    let fn_call = parent.and_then(|p| {
+        lang_items::FN_TRAITS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
+    });
 
-    let operator = (!from_hir_call)
-        .then(|| parent)
-        .flatten()
-        .and_then(|p| tcx.lang_items().group(LangItemGroup::Op).iter().find(|did| **did == p));
+    let operator = if !from_hir_call && let Some(p) = parent {
+        lang_items::OPERATORS.iter().filter_map(|&l| tcx.lang_items().get(l)).find(|&id| id == p)
+    } else {
+        None
+    };
 
     let is_deref = !from_hir_call && tcx.is_diagnostic_item(sym::deref_method, method_did);
 
     // Check for a 'special' use of 'self' -
     // an FnOnce call, an operator (e.g. `<<`), or a
     // deref coercion.
-    let kind = if let Some(&trait_id) = fn_call {
+    let kind = if let Some(trait_id) = fn_call {
         Some(CallKind::FnCall { fn_trait_id: trait_id, self_ty: method_substs.type_at(0) })
-    } else if let Some(&trait_id) = operator {
+    } else if let Some(trait_id) = operator {
         Some(CallKind::Operator { self_arg, trait_id, self_ty: method_substs.type_at(0) })
     } else if is_deref {
         let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| {
diff --git a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
index 42c84fdd2d1..48ddb54b79e 100644
--- a/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/monomorphize.ftl
@@ -21,6 +21,3 @@ monomorphize_large_assignments =
     moving {$size} bytes
     .label = value moved from here
     .note = The current maximum size is {$limit}, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
-
-monomorphize_requires_lang_item =
-    requires `{$lang_item}` lang_item
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index ca615a4912a..72ed73e81b4 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -12,35 +12,56 @@ use crate::errors::LangItemError;
 use crate::{MethodKind, Target};
 
 use rustc_ast as ast;
-use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_macros::HashStable_Generic;
 use rustc_span::symbol::{kw, sym, Symbol};
 use rustc_span::Span;
 
-use std::sync::LazyLock;
-
-pub enum LangItemGroup {
-    Op,
-    Fn,
+/// All of the language items, defined or not.
+/// Defined lang items can come from the current crate or its dependencies.
+#[derive(HashStable_Generic, Debug)]
+pub struct LanguageItems {
+    /// Mappings from lang items to their possibly found [`DefId`]s.
+    /// The index corresponds to the order in [`LangItem`].
+    items: [Option<DefId>; std::mem::variant_count::<LangItem>()],
+    /// Lang items that were not found during collection.
+    pub missing: Vec<LangItem>,
 }
 
-const NUM_GROUPS: usize = 2;
+impl LanguageItems {
+    /// Construct an empty collection of lang items and no missing ones.
+    pub fn new() -> Self {
+        Self { items: [None; std::mem::variant_count::<LangItem>()], missing: Vec::new() }
+    }
+
+    pub fn get(&self, item: LangItem) -> Option<DefId> {
+        self.items[item as usize]
+    }
 
-macro_rules! expand_group {
-    () => {
-        None
-    };
-    ($group:expr) => {
-        Some($group)
-    };
+    pub fn set(&mut self, item: LangItem, def_id: DefId) {
+        self.items[item as usize] = Some(def_id);
+    }
+
+    /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
+    /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
+    /// returns an error encapsulating the `LangItem`.
+    pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
+        self.get(it).ok_or_else(|| LangItemError(it))
+    }
+
+    pub fn iter<'a>(&'a self) -> impl Iterator<Item = (LangItem, DefId)> + 'a {
+        self.items
+            .iter()
+            .enumerate()
+            .filter_map(|(i, id)| id.map(|id| (LangItem::from_u32(i as u32).unwrap(), id)))
+    }
 }
 
 // The actual lang items defined come at the end of this file in one handy table.
 // So you probably just want to nip down to the end.
 macro_rules! language_item_table {
     (
-        $( $(#[$attr:meta])* $variant:ident $($group:expr)?, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
+        $( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
     ) => {
 
         enum_from_u32! {
@@ -66,12 +87,17 @@ macro_rules! language_item_table {
                 }
             }
 
-            /// The [group](LangItemGroup) that this lang item belongs to,
-            /// or `None` if it doesn't belong to a group.
-            pub fn group(self) -> Option<LangItemGroup> {
-                use LangItemGroup::*;
+            /// Opposite of [`LangItem::name`]
+            pub fn from_name(name: Symbol) -> Option<Self> {
+                match name {
+                    $( $module::$name => Some(LangItem::$variant), )*
+                    _ => None,
+                }
+            }
+
+            pub fn target(self) -> Target {
                 match self {
-                    $( LangItem::$variant => expand_group!($($group)*), )*
+                    $( LangItem::$variant => $target, )*
                 }
             }
 
@@ -82,50 +108,7 @@ macro_rules! language_item_table {
             }
         }
 
-        /// All of the language items, defined or not.
-        /// Defined lang items can come from the current crate or its dependencies.
-        #[derive(HashStable_Generic, Debug)]
-        pub struct LanguageItems {
-            /// Mappings from lang items to their possibly found [`DefId`]s.
-            /// The index corresponds to the order in [`LangItem`].
-            pub items: Vec<Option<DefId>>,
-            /// Lang items that were not found during collection.
-            pub missing: Vec<LangItem>,
-            /// Mapping from [`LangItemGroup`] discriminants to all
-            /// [`DefId`]s of lang items in that group.
-            pub groups: [Vec<DefId>; NUM_GROUPS],
-        }
-
         impl LanguageItems {
-            /// Construct an empty collection of lang items and no missing ones.
-            pub fn new() -> Self {
-                fn init_none(_: LangItem) -> Option<DefId> { None }
-                const EMPTY: Vec<DefId> = Vec::new();
-
-                Self {
-                    items: vec![$(init_none(LangItem::$variant)),*],
-                    missing: Vec::new(),
-                    groups: [EMPTY; NUM_GROUPS],
-                }
-            }
-
-            /// Returns the mappings to the possibly found `DefId`s for each lang item.
-            pub fn items(&self) -> &[Option<DefId>] {
-                &*self.items
-            }
-
-            /// Requires that a given `LangItem` was bound and returns the corresponding `DefId`.
-            /// If it wasn't bound, e.g. due to a missing `#[lang = "<it.name()>"]`,
-            /// returns an error encapsulating the `LangItem`.
-            pub fn require(&self, it: LangItem) -> Result<DefId, LangItemError> {
-                self.items[it as usize].ok_or_else(|| LangItemError(it))
-            }
-
-            /// Returns the [`DefId`]s of all lang items in a group.
-            pub fn group(&self, group: LangItemGroup) -> &[DefId] {
-                self.groups[group as usize].as_ref()
-            }
-
             $(
                 #[doc = concat!("Returns the [`DefId`] of the `", stringify!($name), "` lang item if it is defined.")]
                 pub fn $method(&self) -> Option<DefId> {
@@ -133,15 +116,6 @@ macro_rules! language_item_table {
                 }
             )*
         }
-
-        /// A mapping from the name of the lang item to its order and the form it must be of.
-        pub static ITEM_REFS: LazyLock<FxIndexMap<Symbol, (usize, Target)>> = LazyLock::new(|| {
-            let mut item_refs = FxIndexMap::default();
-            $( item_refs.insert($module::$name, (LangItem::$variant as usize, $target)); )*
-            item_refs
-        });
-
-// End of the macro
     }
 }
 
@@ -196,30 +170,30 @@ language_item_table! {
     TransmuteOpts,           sym::transmute_opts,      transmute_opts,             Target::Struct,         GenericRequirement::Exact(0);
     TransmuteTrait,          sym::transmute_trait,     transmute_trait,            Target::Trait,          GenericRequirement::Exact(3);
 
-    Add(Op),                 sym::add,                 add_trait,                  Target::Trait,          GenericRequirement::Exact(1);
-    Sub(Op),                 sym::sub,                 sub_trait,                  Target::Trait,          GenericRequirement::Exact(1);
-    Mul(Op),                 sym::mul,                 mul_trait,                  Target::Trait,          GenericRequirement::Exact(1);
-    Div(Op),                 sym::div,                 div_trait,                  Target::Trait,          GenericRequirement::Exact(1);
-    Rem(Op),                 sym::rem,                 rem_trait,                  Target::Trait,          GenericRequirement::Exact(1);
-    Neg(Op),                 sym::neg,                 neg_trait,                  Target::Trait,          GenericRequirement::Exact(0);
-    Not(Op),                 sym::not,                 not_trait,                  Target::Trait,          GenericRequirement::Exact(0);
-    BitXor(Op),              sym::bitxor,              bitxor_trait,               Target::Trait,          GenericRequirement::Exact(1);
-    BitAnd(Op),              sym::bitand,              bitand_trait,               Target::Trait,          GenericRequirement::Exact(1);
-    BitOr(Op),               sym::bitor,               bitor_trait,                Target::Trait,          GenericRequirement::Exact(1);
-    Shl(Op),                 sym::shl,                 shl_trait,                  Target::Trait,          GenericRequirement::Exact(1);
-    Shr(Op),                 sym::shr,                 shr_trait,                  Target::Trait,          GenericRequirement::Exact(1);
-    AddAssign(Op),           sym::add_assign,          add_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
-    SubAssign(Op),           sym::sub_assign,          sub_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
-    MulAssign(Op),           sym::mul_assign,          mul_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
-    DivAssign(Op),           sym::div_assign,          div_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
-    RemAssign(Op),           sym::rem_assign,          rem_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
-    BitXorAssign(Op),        sym::bitxor_assign,       bitxor_assign_trait,        Target::Trait,          GenericRequirement::Exact(1);
-    BitAndAssign(Op),        sym::bitand_assign,       bitand_assign_trait,        Target::Trait,          GenericRequirement::Exact(1);
-    BitOrAssign(Op),         sym::bitor_assign,        bitor_assign_trait,         Target::Trait,          GenericRequirement::Exact(1);
-    ShlAssign(Op),           sym::shl_assign,          shl_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
-    ShrAssign(Op),           sym::shr_assign,          shr_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
-    Index(Op),               sym::index,               index_trait,                Target::Trait,          GenericRequirement::Exact(1);
-    IndexMut(Op),            sym::index_mut,           index_mut_trait,            Target::Trait,          GenericRequirement::Exact(1);
+    Add,                     sym::add,                 add_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Sub,                     sym::sub,                 sub_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Mul,                     sym::mul,                 mul_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Div,                     sym::div,                 div_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Rem,                     sym::rem,                 rem_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Neg,                     sym::neg,                 neg_trait,                  Target::Trait,          GenericRequirement::Exact(0);
+    Not,                     sym::not,                 not_trait,                  Target::Trait,          GenericRequirement::Exact(0);
+    BitXor,                  sym::bitxor,              bitxor_trait,               Target::Trait,          GenericRequirement::Exact(1);
+    BitAnd,                  sym::bitand,              bitand_trait,               Target::Trait,          GenericRequirement::Exact(1);
+    BitOr,                   sym::bitor,               bitor_trait,                Target::Trait,          GenericRequirement::Exact(1);
+    Shl,                     sym::shl,                 shl_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    Shr,                     sym::shr,                 shr_trait,                  Target::Trait,          GenericRequirement::Exact(1);
+    AddAssign,               sym::add_assign,          add_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    SubAssign,               sym::sub_assign,          sub_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    MulAssign,               sym::mul_assign,          mul_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    DivAssign,               sym::div_assign,          div_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    RemAssign,               sym::rem_assign,          rem_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    BitXorAssign,            sym::bitxor_assign,       bitxor_assign_trait,        Target::Trait,          GenericRequirement::Exact(1);
+    BitAndAssign,            sym::bitand_assign,       bitand_assign_trait,        Target::Trait,          GenericRequirement::Exact(1);
+    BitOrAssign,             sym::bitor_assign,        bitor_assign_trait,         Target::Trait,          GenericRequirement::Exact(1);
+    ShlAssign,               sym::shl_assign,          shl_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    ShrAssign,               sym::shr_assign,          shr_assign_trait,           Target::Trait,          GenericRequirement::Exact(1);
+    Index,                   sym::index,               index_trait,                Target::Trait,          GenericRequirement::Exact(1);
+    IndexMut,                sym::index_mut,           index_mut_trait,            Target::Trait,          GenericRequirement::Exact(1);
 
     UnsafeCell,              sym::unsafe_cell,         unsafe_cell_type,           Target::Struct,         GenericRequirement::None;
     VaList,                  sym::va_list,             va_list,                    Target::Struct,         GenericRequirement::None;
@@ -229,9 +203,9 @@ language_item_table! {
     DerefTarget,             sym::deref_target,        deref_target,               Target::AssocTy,        GenericRequirement::None;
     Receiver,                sym::receiver,            receiver_trait,             Target::Trait,          GenericRequirement::None;
 
-    Fn(Fn),                  kw::Fn,                   fn_trait,                   Target::Trait,          GenericRequirement::Exact(1);
-    FnMut(Fn),               sym::fn_mut,              fn_mut_trait,               Target::Trait,          GenericRequirement::Exact(1);
-    FnOnce(Fn),              sym::fn_once,             fn_once_trait,              Target::Trait,          GenericRequirement::Exact(1);
+    Fn,                      kw::Fn,                   fn_trait,                   Target::Trait,          GenericRequirement::Exact(1);
+    FnMut,                   sym::fn_mut,              fn_mut_trait,               Target::Trait,          GenericRequirement::Exact(1);
+    FnOnce,                  sym::fn_once,             fn_once_trait,              Target::Trait,          GenericRequirement::Exact(1);
 
     FnOnceOutput,            sym::fn_once_output,      fn_once_output,             Target::AssocTy,        GenericRequirement::None;
 
@@ -241,8 +215,8 @@ language_item_table! {
     Unpin,                   sym::unpin,               unpin_trait,                Target::Trait,          GenericRequirement::None;
     Pin,                     sym::pin,                 pin_type,                   Target::Struct,         GenericRequirement::None;
 
-    PartialEq(Op),           sym::eq,                  eq_trait,                   Target::Trait,          GenericRequirement::Exact(1);
-    PartialOrd(Op),          sym::partial_ord,         partial_ord_trait,          Target::Trait,          GenericRequirement::Exact(1);
+    PartialEq,               sym::eq,                  eq_trait,                   Target::Trait,          GenericRequirement::Exact(1);
+    PartialOrd,              sym::partial_ord,         partial_ord_trait,          Target::Trait,          GenericRequirement::Exact(1);
 
     // A number of panic-related lang items. The `panic` item corresponds to divide-by-zero and
     // various panic cases with `match`. The `panic_bounds_check` item is for indexing arrays.
@@ -338,3 +312,34 @@ pub enum GenericRequirement {
     Minimum(usize),
     Exact(usize),
 }
+
+pub static FN_TRAITS: &'static [LangItem] = &[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce];
+
+pub static OPERATORS: &'static [LangItem] = &[
+    LangItem::Add,
+    LangItem::Sub,
+    LangItem::Mul,
+    LangItem::Div,
+    LangItem::Rem,
+    LangItem::Neg,
+    LangItem::Not,
+    LangItem::BitXor,
+    LangItem::BitAnd,
+    LangItem::BitOr,
+    LangItem::Shl,
+    LangItem::Shr,
+    LangItem::AddAssign,
+    LangItem::SubAssign,
+    LangItem::MulAssign,
+    LangItem::DivAssign,
+    LangItem::RemAssign,
+    LangItem::BitXorAssign,
+    LangItem::BitAndAssign,
+    LangItem::BitOrAssign,
+    LangItem::ShlAssign,
+    LangItem::ShrAssign,
+    LangItem::Index,
+    LangItem::IndexMut,
+    LangItem::PartialEq,
+    LangItem::PartialOrd,
+];
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 1c4aa420c9b..1c55cd8fee8 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -5,10 +5,10 @@
 #![feature(associated_type_defaults)]
 #![feature(closure_track_caller)]
 #![feature(const_btree_len)]
-#![feature(once_cell)]
 #![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(rustc_attrs)]
+#![feature(variant_count)]
 #![recursion_limit = "256"]
 #![deny(rustc::untranslatable_diagnostic)]
 #![deny(rustc::diagnostic_outside_of_impl)]
diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs
index da9c9c1216e..d8e5dd4ffdc 100644
--- a/compiler/rustc_hir/src/weak_lang_items.rs
+++ b/compiler/rustc_hir/src/weak_lang_items.rs
@@ -1,53 +1,31 @@
 //! Validity checking for weak lang items
 
-use crate::def_id::DefId;
-use crate::{lang_items, LangItem, LanguageItems};
+use crate::LangItem;
 
-use rustc_ast as ast;
-use rustc_data_structures::fx::FxIndexMap;
 use rustc_span::symbol::{sym, Symbol};
 
-use std::sync::LazyLock;
-
 macro_rules! weak_lang_items {
-    ($($name:ident, $item:ident, $sym:ident;)*) => (
-
-pub static WEAK_ITEMS_REFS: LazyLock<FxIndexMap<Symbol, LangItem>> = LazyLock::new(|| {
-    let mut map = FxIndexMap::default();
-    $(map.insert(sym::$name, LangItem::$item);)*
-    map
-});
-
-pub static WEAK_ITEMS_SYMBOLS: LazyLock<FxIndexMap<LangItem, Symbol>> = LazyLock::new(|| {
-    let mut map = FxIndexMap::default();
-    $(map.insert(LangItem::$item, sym::$sym);)*
-    map
-});
-
-pub fn link_name(attrs: &[ast::Attribute]) -> Option<Symbol>
-{
-    lang_items::extract(attrs).and_then(|(name, _)| {
-        $(if name == sym::$name {
-            Some(sym::$sym)
-        } else)* {
-            None
+    ($($item:ident, $sym:ident;)*) => {
+        pub static WEAK_LANG_ITEMS: &[LangItem] = &[$(LangItem::$item,)*];
+
+        impl LangItem {
+            pub fn is_weak(self) -> bool {
+                matches!(self, $(LangItem::$item)|*)
+            }
+
+            pub fn link_name(self) -> Option<Symbol> {
+                match self {
+                    $( LangItem::$item => Some(sym::$sym),)*
+                    _ => None,
+                }
+            }
         }
-    })
-}
-
-impl LanguageItems {
-    pub fn is_weak_lang_item(&self, item_def_id: DefId) -> bool {
-        let did = Some(item_def_id);
-
-        $(self.$name() == did)||*
     }
 }
 
-) }
-
 weak_lang_items! {
-    panic_impl,         PanicImpl,          rust_begin_unwind;
-    eh_personality,     EhPersonality,      rust_eh_personality;
-    eh_catch_typeinfo,  EhCatchTypeinfo,    rust_eh_catch_typeinfo;
-    oom,                Oom,                rust_oom;
+    PanicImpl,          rust_begin_unwind;
+    EhPersonality,      rust_eh_personality;
+    EhCatchTypeinfo,    rust_eh_catch_typeinfo;
+    Oom,                rust_oom;
 }
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 38f195dabb9..39b178f5976 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -23,7 +23,6 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{walk_generics, Visitor as _};
-use rustc_hir::lang_items::LangItem;
 use rustc_hir::{GenericArg, GenericArgs, OpaqueTyOrigin};
 use rustc_middle::middle::stability::AllowUnstable;
 use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef};
@@ -884,9 +883,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         }
 
-        let sized_def_id = tcx.lang_items().require(LangItem::Sized);
+        let sized_def_id = tcx.lang_items().sized_trait();
         match (&sized_def_id, unbound) {
-            (Ok(sized_def_id), Some(tpb))
+            (Some(sized_def_id), Some(tpb))
                 if tpb.path.res == Res::Def(DefKind::Trait, *sized_def_id) =>
             {
                 // There was in fact a `?Sized` bound, return without doing anything
@@ -906,7 +905,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // There was no `?Sized` bound; add implicitly sized if `Sized` is available.
             }
         }
-        if sized_def_id.is_err() {
+        if sized_def_id.is_none() {
             // No lang item for `Sized`, so we can't add it as a bound.
             return;
         }
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 346d2e2fc4b..65a1d61e87c 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -27,8 +27,8 @@ use rustc_hir as hir;
 use rustc_hir::def::CtorKind;
 use rustc_hir::def_id::{DefId, LocalDefId, LOCAL_CRATE};
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::weak_lang_items;
-use rustc_hir::{GenericParamKind, Node};
+use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
+use rustc_hir::{lang_items, GenericParamKind, LangItem, Node};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::mono::Linkage;
@@ -2104,12 +2104,15 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
     // strippable by the linker.
     //
     // Additionally weak lang items have predetermined symbol names.
-    if tcx.is_weak_lang_item(did.to_def_id()) {
+    if WEAK_LANG_ITEMS.iter().any(|&l| tcx.lang_items().get(l) == Some(did.to_def_id())) {
         codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
     }
-    if let Some(name) = weak_lang_items::link_name(attrs) {
-        codegen_fn_attrs.export_name = Some(name);
-        codegen_fn_attrs.link_name = Some(name);
+    if let Some((name, _)) = lang_items::extract(attrs)
+        && let Some(lang_item) = LangItem::from_name(name)
+        && let Some(link_name) = lang_item.link_name()
+    {
+        codegen_fn_attrs.export_name = Some(link_name);
+        codegen_fn_attrs.link_name = Some(link_name);
     }
     check_link_name_xor_ordinal(tcx, &codegen_fn_attrs, link_ordinal_span);
 
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 691e3d0f8f9..17a7532044a 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -15,7 +15,6 @@ use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
 use rustc_hir::diagnostic_items::DiagnosticItems;
-use rustc_hir::lang_items;
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_middle::metadata::ModChild;
 use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
@@ -967,7 +966,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     }
 
     /// Iterates over the language items in the given crate.
-    fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
+    fn get_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] {
         tcx.arena.alloc_from_iter(
             self.root
                 .lang_items
@@ -1319,7 +1318,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
         )
     }
 
-    fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
+    fn get_missing_lang_items(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] {
         tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode(self))
     }
 
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 049514ec7b2..87fa69e1639 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -17,7 +17,7 @@ use rustc_hir::def_id::{
 };
 use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::{
@@ -1905,22 +1905,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         self.lazy_array(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
     }
 
-    fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, usize)> {
+    fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, LangItem)> {
         empty_proc_macro!(self);
-        let tcx = self.tcx;
-        let lang_items = tcx.lang_items();
-        let lang_items = lang_items.items().iter();
-        self.lazy_array(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
-            if let Some(def_id) = opt_def_id {
-                if def_id.is_local() {
-                    return Some((def_id.index, i));
-                }
-            }
-            None
+        let lang_items = self.tcx.lang_items().iter();
+        self.lazy_array(lang_items.filter_map(|(lang_item, def_id)| {
+            def_id.as_local().map(|id| (id.local_def_index, lang_item))
         }))
     }
 
-    fn encode_lang_items_missing(&mut self) -> LazyArray<lang_items::LangItem> {
+    fn encode_lang_items_missing(&mut self) -> LazyArray<LangItem> {
         empty_proc_macro!(self);
         let tcx = self.tcx;
         self.lazy_array(&tcx.lang_items().missing)
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 27dc8ff16ac..774cff2075d 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -12,7 +12,7 @@ use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
 use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
 use rustc_hir::definitions::DefKey;
-use rustc_hir::lang_items;
+use rustc_hir::lang_items::LangItem;
 use rustc_index::bit_set::{BitSet, FiniteBitSet};
 use rustc_index::vec::IndexVec;
 use rustc_middle::metadata::ModChild;
@@ -230,8 +230,8 @@ pub(crate) struct CrateRoot {
     dylib_dependency_formats: LazyArray<Option<LinkagePreference>>,
     lib_features: LazyArray<(Symbol, Option<Symbol>)>,
     stability_implications: LazyArray<(Symbol, Symbol)>,
-    lang_items: LazyArray<(DefIndex, usize)>,
-    lang_items_missing: LazyArray<lang_items::LangItem>,
+    lang_items: LazyArray<(DefIndex, LangItem)>,
+    lang_items_missing: LazyArray<LangItem>,
     diagnostic_items: LazyArray<(Symbol, DefIndex)>,
     native_libraries: LazyArray<NativeLib>,
     foreign_modules: LazyArray<ForeignModule>,
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index 31c20fa14aa..dd4332d0db6 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -36,10 +36,6 @@ impl<'tcx> TyCtxt<'tcx> {
             _ => None,
         }
     }
-
-    pub fn is_weak_lang_item(self, item_def_id: DefId) -> bool {
-        self.lang_items().is_weak_lang_item(item_def_id)
-    }
 }
 
 /// Returns `true` if the specified `lang_item` must be present for this
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 3d720f09b4f..a098e570305 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1705,7 +1705,7 @@ rustc_queries! {
     }
 
     /// Returns the lang items defined in another crate by loading it from metadata.
-    query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, usize)] {
+    query defined_lang_items(_: CrateNum) -> &'tcx [(DefId, LangItem)] {
         desc { "calculating the lang items defined in a crate" }
         separate_provide_extern
     }
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 3d7e2a0839a..8e24f4813a7 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2456,7 +2456,7 @@ impl<'tcx> TyCtxt<'tcx> {
 
     #[inline]
     pub fn mk_lang_item(self, ty: Ty<'tcx>, item: LangItem) -> Option<Ty<'tcx>> {
-        let def_id = self.lang_items().require(item).ok()?;
+        let def_id = self.lang_items().get(item)?;
         Some(self.mk_generic_adt(def_id, ty))
     }
 
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index a71218e6997..3cfddd75462 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -201,7 +201,7 @@ use std::iter;
 use std::ops::Range;
 use std::path::PathBuf;
 
-use crate::errors::{LargeAssignmentsLint, RecursionLimit, RequiresLangItem, TypeLengthLimit};
+use crate::errors::{LargeAssignmentsLint, RecursionLimit, TypeLengthLimit};
 
 #[derive(PartialEq)]
 pub enum MonoItemCollectionMode {
@@ -1298,14 +1298,7 @@ impl<'v> RootCollector<'_, 'v> {
             return;
         };
 
-        let start_def_id = match self.tcx.lang_items().require(LangItem::Start) {
-            Ok(s) => s,
-            Err(lang_item_err) => {
-                self.tcx
-                    .sess
-                    .emit_fatal(RequiresLangItem { lang_item: lang_item_err.0.name().to_string() });
-            }
-        };
+        let start_def_id = self.tcx.require_lang_item(LangItem::Start, None);
         let main_ret_ty = self.tcx.fn_sig(main_def_id).output();
 
         // Given that `main()` has no arguments,
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index ce097b8d846..870d50728bd 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -32,12 +32,6 @@ pub struct TypeLengthLimit {
     pub type_length: usize,
 }
 
-#[derive(Diagnostic)]
-#[diag(monomorphize_requires_lang_item)]
-pub struct RequiresLangItem {
-    pub lang_item: String,
-}
-
 pub struct UnusedGenericParams {
     pub span: Span,
     pub param_spans: Vec<Span>,
diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs
index df811be2a7e..188efc528ef 100644
--- a/compiler/rustc_passes/src/lang_items.rs
+++ b/compiler/rustc_passes/src/lang_items.rs
@@ -16,7 +16,7 @@ use crate::weak_lang_items;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
-use rustc_hir::lang_items::{extract, GenericRequirement, ITEM_REFS};
+use rustc_hir::lang_items::{extract, GenericRequirement};
 use rustc_hir::{HirId, LangItem, LanguageItems, Target};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::cstore::ExternCrate;
@@ -43,17 +43,17 @@ impl<'tcx> LanguageItemCollector<'tcx> {
     fn check_for_lang(&mut self, actual_target: Target, hir_id: HirId) {
         let attrs = self.tcx.hir().attrs(hir_id);
         if let Some((name, span)) = extract(&attrs) {
-            match ITEM_REFS.get(&name).cloned() {
+            match LangItem::from_name(name) {
                 // Known lang item with attribute on correct target.
-                Some((item_index, expected_target)) if actual_target == expected_target => {
-                    self.collect_item_extended(item_index, hir_id, span);
+                Some(lang_item) if actual_target == lang_item.target() => {
+                    self.collect_item_extended(lang_item, hir_id, span);
                 }
                 // Known lang item with attribute on incorrect target.
-                Some((_, expected_target)) => {
+                Some(lang_item) => {
                     self.tcx.sess.emit_err(LangItemOnIncorrectTarget {
                         span,
                         name,
-                        expected_target,
+                        expected_target: lang_item.target(),
                         actual_target,
                     });
                 }
@@ -65,12 +65,12 @@ impl<'tcx> LanguageItemCollector<'tcx> {
         }
     }
 
-    fn collect_item(&mut self, item_index: usize, item_def_id: DefId) {
+    fn collect_item(&mut self, lang_item: LangItem, item_def_id: DefId) {
         // Check for duplicates.
-        if let Some(original_def_id) = self.items.items[item_index] {
+        if let Some(original_def_id) = self.items.get(lang_item) {
             if original_def_id != item_def_id {
                 let local_span = self.tcx.hir().span_if_local(item_def_id);
-                let lang_item_name = LangItem::from_u32(item_index as u32).unwrap().name();
+                let lang_item_name = lang_item.name();
                 let crate_name = self.tcx.crate_name(item_def_id.krate);
                 let mut dependency_of = Empty;
                 let is_local = item_def_id.is_local();
@@ -139,17 +139,13 @@ impl<'tcx> LanguageItemCollector<'tcx> {
         }
 
         // Matched.
-        self.items.items[item_index] = Some(item_def_id);
-        if let Some(group) = LangItem::from_u32(item_index as u32).unwrap().group() {
-            self.items.groups[group as usize].push(item_def_id);
-        }
+        self.items.set(lang_item, item_def_id);
     }
 
     // Like collect_item() above, but also checks whether the lang item is declared
     // with the right number of generic arguments.
-    fn collect_item_extended(&mut self, item_index: usize, hir_id: HirId, span: Span) {
+    fn collect_item_extended(&mut self, lang_item: LangItem, hir_id: HirId, span: Span) {
         let item_def_id = self.tcx.hir().local_def_id(hir_id).to_def_id();
-        let lang_item = LangItem::from_u32(item_index as u32).unwrap();
         let name = lang_item.name();
 
         // Now check whether the lang_item has the expected number of generic
@@ -197,7 +193,7 @@ impl<'tcx> LanguageItemCollector<'tcx> {
             }
         }
 
-        self.collect_item(item_index, item_def_id);
+        self.collect_item(lang_item, item_def_id);
     }
 }
 
@@ -208,8 +204,8 @@ fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems {
 
     // Collect lang items in other crates.
     for &cnum in tcx.crates(()).iter() {
-        for &(def_id, item_index) in tcx.defined_lang_items(cnum).iter() {
-            collector.collect_item(item_index, def_id);
+        for &(def_id, lang_item) in tcx.defined_lang_items(cnum).iter() {
+            collector.collect_item(lang_item, def_id);
         }
     }
 
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 10d5fc5d671..73ea06a6370 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -380,11 +380,9 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
         })
         .collect::<Vec<_>>();
 
-    for item in tcx.lang_items().items().iter() {
-        if let Some(def_id) = *item {
-            if let Some(def_id) = def_id.as_local() {
-                reachable_context.worklist.push(def_id);
-            }
+    for (_, def_id) in tcx.lang_items().iter() {
+        if let Some(def_id) = def_id.as_local() {
+            reachable_context.worklist.push(def_id);
         }
     }
     {
diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs
index 959ee600c07..94d6a405b53 100644
--- a/compiler/rustc_passes/src/weak_lang_items.rs
+++ b/compiler/rustc_passes/src/weak_lang_items.rs
@@ -2,7 +2,7 @@
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::lang_items::{self, LangItem};
-use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS;
+use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
 use rustc_middle::middle::lang_items::required;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::CrateType;
@@ -29,8 +29,8 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem
     for id in crate_items.foreign_items() {
         let attrs = tcx.hir().attrs(id.hir_id());
         if let Some((lang_item, _)) = lang_items::extract(attrs) {
-            if let Some(&item) = WEAK_ITEMS_REFS.get(&lang_item) {
-                if items.require(item).is_err() {
+            if let Some(item) = LangItem::from_name(lang_item) && item.is_weak() {
+                if items.get(item).is_none() {
                     items.missing.push(item);
                 }
             } else {
@@ -65,8 +65,8 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
         }
     }
 
-    for (name, &item) in WEAK_ITEMS_REFS.iter() {
-        if missing.contains(&item) && required(tcx, item) && items.require(item).is_err() {
+    for &item in WEAK_LANG_ITEMS.iter() {
+        if missing.contains(&item) && required(tcx, item) && items.get(item).is_none() {
             if item == LangItem::PanicImpl {
                 tcx.sess.emit_err(MissingPanicHandler);
             } else if item == LangItem::Oom {
@@ -75,7 +75,7 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) {
                     tcx.sess.emit_note(MissingAllocErrorHandler);
                 }
             } else {
-                tcx.sess.emit_err(MissingLangItem { name: *name });
+                tcx.sess.emit_err(MissingLangItem { name: item.name() });
             }
         }
     }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 1217d264a9c..dacce5cd2f6 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -974,7 +974,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                                 // useful for less general traits.
                                 if peeled
                                     && !self.tcx.trait_is_auto(def_id)
-                                    && !self.tcx.lang_items().items().contains(&Some(def_id))
+                                    && !self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
                                 {
                                     let trait_ref = trait_pred.to_poly_trait_ref();
                                     let impl_candidates =
@@ -1898,7 +1898,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let def_id = trait_ref.def_id();
         if impl_candidates.is_empty() {
             if self.tcx.trait_is_auto(def_id)
-                || self.tcx.lang_items().items().contains(&Some(def_id))
+                || self.tcx.lang_items().iter().any(|(_, id)| id == def_id)
                 || self.tcx.get_diagnostic_name(def_id).is_some()
             {
                 // Mentioning implementers of `Copy`, `Debug` and friends is not useful.
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 8c41d9d240c..d7606d88803 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -1019,7 +1019,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         let mut never_suggest_borrow: Vec<_> =
             [LangItem::Copy, LangItem::Clone, LangItem::Unpin, LangItem::Sized]
                 .iter()
-                .filter_map(|lang_item| self.tcx.lang_items().require(*lang_item).ok())
+                .filter_map(|lang_item| self.tcx.lang_items().get(*lang_item))
                 .collect();
 
         if let Some(def_id) = self.tcx.get_diagnostic_item(sym::Send) {
diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs
index 3bf2d7e4ea4..54c316358a1 100644
--- a/src/tools/clippy/clippy_lints/src/lifetimes.rs
+++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs
@@ -6,11 +6,12 @@ use rustc_hir::intravisit::{
     walk_fn_decl, walk_generic_param, walk_generics, walk_impl_item_ref, walk_item, walk_param_bound,
     walk_poly_trait_ref, walk_trait_ref, walk_ty, Visitor,
 };
+use rustc_hir::lang_items;
 use rustc_hir::FnRetTy::Return;
 use rustc_hir::{
     BareFnTy, BodyId, FnDecl, GenericArg, GenericBound, GenericParam, GenericParamKind, Generics, Impl, ImplItem,
-    ImplItemKind, Item, ItemKind, LangItem, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn,
-    TraitItem, TraitItemKind, Ty, TyKind, WherePredicate,
+    ImplItemKind, Item, ItemKind, Lifetime, LifetimeName, ParamName, PolyTraitRef, PredicateOrigin, TraitFn, TraitItem,
+    TraitItemKind, Ty, TyKind, WherePredicate,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter as middle_nested_filter;
@@ -364,8 +365,6 @@ fn unique_lifetimes(lts: &[RefLt]) -> usize {
     lts.iter().collect::<FxHashSet<_>>().len()
 }
 
-const CLOSURE_TRAIT_BOUNDS: [LangItem; 3] = [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce];
-
 /// A visitor usable for `rustc_front::visit::walk_ty()`.
 struct RefVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,
@@ -424,12 +423,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
 
     fn visit_poly_trait_ref(&mut self, poly_tref: &'tcx PolyTraitRef<'tcx>) {
         let trait_ref = &poly_tref.trait_ref;
-        if CLOSURE_TRAIT_BOUNDS.iter().any(|&item| {
-            self.cx
-                .tcx
-                .lang_items()
-                .require(item)
-                .map_or(false, |id| Some(id) == trait_ref.trait_def_id())
+        if let Some(id) = trait_ref.trait_def_id() && lang_items::FN_TRAITS.iter().any(|&item| {
+            self.cx.tcx.lang_items().get(item) == Some(id)
         }) {
             let mut sub_visitor = RefVisitor::new(self.cx);
             sub_visitor.visit_trait_ref(trait_ref);
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index 3181bc86d17..6abbab278fe 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -92,7 +92,7 @@ fn check_into_iter(
         && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
         && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
         && let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
-        && cx.tcx.lang_items().require(hir::LangItem::IntoIterIntoIter).ok() == Some(into_iter_def_id)
+        && Some(into_iter_def_id) == cx.tcx.lang_items().into_iter_fn()
         && match_acceptable_type(cx, left_expr, msrv)
         && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) {
         suggest(cx, parent_expr, left_expr, target_expr);
diff --git a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
index cc26b0f7fa8..4720a6e6888 100644
--- a/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/bind_instead_of_map.rs
@@ -41,7 +41,7 @@ pub(crate) trait BindInsteadOfMap {
     const GOOD_METHOD_NAME: &'static str;
 
     fn no_op_msg(cx: &LateContext<'_>) -> Option<String> {
-        let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
+        let variant_id = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)?;
         let item_id = cx.tcx.parent(variant_id);
         Some(format!(
             "using `{}.{}({})`, which is a no-op",
@@ -52,7 +52,7 @@ pub(crate) trait BindInsteadOfMap {
     }
 
     fn lint_msg(cx: &LateContext<'_>) -> Option<String> {
-        let variant_id = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM).ok()?;
+        let variant_id = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM)?;
         let item_id = cx.tcx.parent(variant_id);
         Some(format!(
             "using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`",
@@ -144,7 +144,7 @@ pub(crate) trait BindInsteadOfMap {
     fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) -> bool {
         if_chain! {
             if let Some(adt) = cx.typeck_results().expr_ty(recv).ty_adt_def();
-            if let Ok(vid) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM);
+            if let Some(vid) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM);
             if adt.did() == cx.tcx.parent(vid);
             then {} else { return false; }
         }
@@ -181,7 +181,7 @@ pub(crate) trait BindInsteadOfMap {
 
     fn is_variant(cx: &LateContext<'_>, res: Res) -> bool {
         if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fn), id) = res {
-            if let Ok(variant_id) = cx.tcx.lang_items().require(Self::VARIANT_LANG_ITEM) {
+            if let Some(variant_id) = cx.tcx.lang_items().get(Self::VARIANT_LANG_ITEM) {
                 return cx.tcx.parent(id) == variant_id;
             }
         }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
index 1966a85f7a7..4eb579af7a1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_iter_cloned.rs
@@ -5,7 +5,7 @@ use clippy_utils::source::snippet_opt;
 use clippy_utils::ty::{get_associated_type, get_iterator_item_ty, implements_trait};
 use clippy_utils::{fn_def_id, get_parent_expr};
 use rustc_errors::Applicability;
-use rustc_hir::{def_id::DefId, Expr, ExprKind, LangItem};
+use rustc_hir::{def_id::DefId, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_span::{sym, Symbol};
 
@@ -100,5 +100,5 @@ pub fn check_for_loop_iter(
 
 /// Returns true if the named method is `IntoIterator::into_iter`.
 pub fn is_into_iter(cx: &LateContext<'_>, callee_def_id: DefId) -> bool {
-    cx.tcx.lang_items().require(LangItem::IntoIterIntoIter) == Ok(callee_def_id)
+    Some(callee_def_id) == cx.tcx.lang_items().into_iter_fn()
 }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 3566fe9a0bb..642a64ae77b 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -7,7 +7,7 @@ use clippy_utils::visitors::find_all_ret_expressions;
 use clippy_utils::{fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, return_ty};
 use clippy_utils::{meets_msrv, msrvs};
 use rustc_errors::Applicability;
-use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, LangItem, Node};
+use rustc_hir::{def_id::DefId, BorrowKind, Expr, ExprKind, ItemKind, Node};
 use rustc_hir_typeck::{FnCtxt, Inherited};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::LateContext;
@@ -378,7 +378,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty<
             Node::Expr(parent_expr) => {
                 if let Some((callee_def_id, call_substs, recv, call_args)) = get_callee_substs_and_args(cx, parent_expr)
                 {
-                    if cx.tcx.lang_items().require(LangItem::IntoFutureIntoFuture) == Ok(callee_def_id) {
+                    if Some(callee_def_id) == cx.tcx.lang_items().into_future_fn() {
                         return false;
                     }
 
diff --git a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
index ee9fd94064c..9bbf385fb59 100644
--- a/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/assign_op_pattern.rs
@@ -28,7 +28,7 @@ pub(super) fn check<'tcx>(
             let rty = cx.typeck_results().expr_ty(rhs);
             if_chain! {
                 if let Some((_, lang_item)) = binop_traits(op.node);
-                if let Ok(trait_id) = cx.tcx.lang_items().require(lang_item);
+                if let Some(trait_id) = cx.tcx.lang_items().get(lang_item);
                 let parent_fn = cx.tcx.hir().get_parent_item(e.hir_id).def_id;
                 if trait_ref_of_method(cx, parent_fn)
                     .map_or(true, |t| t.path.res.def_id() != trait_id);
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
index b57b484bdc8..6271ea02731 100644
--- a/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
+++ b/src/tools/clippy/clippy_lints/src/suspicious_trait_impl.rs
@@ -60,8 +60,8 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
         if_chain! {
             if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind;
             if let Some((binop_trait_lang, op_assign_trait_lang)) = binop_traits(binop.node);
-            if let Ok(binop_trait_id) = cx.tcx.lang_items().require(binop_trait_lang);
-            if let Ok(op_assign_trait_id) = cx.tcx.lang_items().require(op_assign_trait_lang);
+            if let Some(binop_trait_id) = cx.tcx.lang_items().get(binop_trait_lang);
+            if let Some(op_assign_trait_id) = cx.tcx.lang_items().get(op_assign_trait_lang);
 
             // Check for more than one binary operation in the implemented function
             // Linting when multiple operations are involved can result in false positives
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for SuspiciousImpl {
                 (&OP_ASSIGN_TRAITS, SUSPICIOUS_OP_ASSIGN_IMPL),
             ]
                 .iter()
-                .find(|&(ts, _)| ts.iter().any(|&t| Ok(trait_id) == cx.tcx.lang_items().require(t)));
+                .find(|&(ts, _)| ts.iter().any(|&t| Some(trait_id) == cx.tcx.lang_items().get(t)));
             if count_binops(body.value) == 1;
             then {
                 span_lint(
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
index 016aacbf9da..ab73f0fc44f 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
@@ -3,7 +3,7 @@ use clippy_utils::{match_def_path, paths};
 use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
+use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
                         );
                 } else {
                     if_chain! {
-                        if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(fun_def_id);
+                        if Some(fun_def_id) == cx.tcx.lang_items().from_fn();
                         if let [.., last_arg] = args;
                         if let ExprKind::Lit(spanned) = &last_arg.kind;
                         if let LitKind::Str(symbol, _) = spanned.node;
diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
index f1cebf0f992..b452be08409 100644
--- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs
+++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs
@@ -3,7 +3,6 @@ use clippy_utils::ty::{match_type, peel_mid_ty_refs_is_mutable};
 use clippy_utils::{fn_def_id, is_trait_method, path_to_local_id, paths, peel_ref_operators};
 use rustc_ast::Mutability;
 use rustc_hir::intravisit::{walk_expr, Visitor};
-use rustc_hir::lang_items::LangItem;
 use rustc_hir::{Block, Expr, ExprKind, HirId, Local, Node, PatKind, PathSegment, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::nested_filter::OnlyBodies;
@@ -132,11 +131,11 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> {
                             // If the Peekable is passed to a function, stop
                             ExprKind::Call(_, args) => {
                                 if let Some(func_did) = fn_def_id(self.cx, expr)
-                                    && let Ok(into_iter_did) = self
+                                    && let Some(into_iter_did) = self
                                         .cx
                                         .tcx
                                         .lang_items()
-                                        .require(LangItem::IntoIterIntoIter)
+                                        .into_iter_fn()
                                     && func_did == into_iter_did
                                 {
                                     // Probably a for loop desugar, stop searching
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index 1f69db1cbca..3743d5d97a7 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -5,7 +5,7 @@ use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts};
 use clippy_utils::{get_parent_expr, is_trait_method, match_def_path, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, HirId, LangItem, MatchSource};
+use rustc_hir::{Expr, ExprKind, HirId, MatchSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -153,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                         }
 
                         if_chain! {
-                            if cx.tcx.lang_items().require(LangItem::FromFrom).ok() == Some(def_id);
+                            if Some(def_id) == cx.tcx.lang_items().from_fn();
                             if same_type_and_consts(a, b);
 
                             then {
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
index 4cf76f53625..2a028c8141f 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs
@@ -152,7 +152,7 @@ impl UnnecessaryDefPath {
                         has_ctor,
                     ),
                     (0, Item::LangItem(item)) => (
-                        format!("{cx_snip}.tcx.lang_items().require(LangItem::{item}).ok() == Some({def_snip})"),
+                        format!("{cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some({def_snip})"),
                         has_ctor,
                     ),
                     // match_trait_method
@@ -184,7 +184,7 @@ impl UnnecessaryDefPath {
                     (3, Item::LangItem(item)) => (
                         format!(
                             "path_res({cx_snip}, {def_snip}).opt_def_id()\
-                                .map_or(false, |id| {cx_snip}.tcx.lang_items().require(LangItem::{item}).ok() == Some(id))",
+                                .map_or(false, |id| {cx_snip}.tcx.lang_items().get(LangItem::{item}) == Some(id))",
                         ),
                         false,
                     ),
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 3ebfc5e00e1..d32cf1a7936 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -247,7 +247,7 @@ pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
 /// For example, use this to check whether a function call or a pattern is `Some(..)`.
 pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> bool {
     if let Res::Def(DefKind::Ctor(..), id) = res
-        && let Ok(lang_id) = cx.tcx.lang_items().require(lang_item)
+        && let Some(lang_id) = cx.tcx.lang_items().get(lang_item)
         && let Some(id) = cx.tcx.opt_parent(id)
     {
         id == lang_id
@@ -303,7 +303,7 @@ pub fn is_lang_item_or_ctor(cx: &LateContext<'_>, did: DefId, item: LangItem) ->
         _ => did,
     };
 
-    cx.tcx.lang_items().require(item).map_or(false, |id| id == did)
+    cx.tcx.lang_items().get(item) == Some(did)
 }
 
 pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 4e024ce4017..3a144c2bb22 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -318,11 +318,7 @@ pub fn is_type_diagnostic_item(cx: &LateContext<'_>, ty: Ty<'_>, diag_item: Symb
 /// Returns `false` if the `LangItem` is not defined.
 pub fn is_type_lang_item(cx: &LateContext<'_>, ty: Ty<'_>, lang_item: hir::LangItem) -> bool {
     match ty.kind() {
-        ty::Adt(adt, _) => cx
-            .tcx
-            .lang_items()
-            .require(lang_item)
-            .map_or(false, |li| li == adt.did()),
+        ty::Adt(adt, _) => cx.tcx.lang_items().get(lang_item) == Some(adt.did()),
         _ => false,
     }
 }