about summary refs log tree commit diff
path: root/src/tools
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-04-28 17:16:28 +0200
committerLukas Wirth <lukastw97@gmail.com>2025-04-28 17:17:39 +0200
commitf479012d0ee77bb8a2a19f6ffb096860498ca5c2 (patch)
treebf187a3bc0bf933f42dd36441bd3f3759d78a40b /src/tools
parent62a48c5fed4a579fecc612de55fa35f9ae4a0a43 (diff)
downloadrust-f479012d0ee77bb8a2a19f6ffb096860498ca5c2.tar.gz
rust-f479012d0ee77bb8a2a19f6ffb096860498ca5c2.zip
refactor: De-arc lang item queries
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs187
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/drop.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs15
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/traits.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/utils.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs54
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs4
23 files changed, 188 insertions, 255 deletions
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index 34cf42d02bd..2cbdbe16f9b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -22,7 +22,7 @@ use crate::{
     hir::generics::GenericParams,
     import_map::ImportMap,
     item_tree::{AttrOwner, ItemTree},
-    lang_item::{self, LangItem, LangItemTarget, LangItems},
+    lang_item::{self, LangItem},
     nameres::{
         DefMap, LocalDefMap,
         assoc::{ImplItems, TraitItems},
@@ -325,9 +325,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
 
     // endregion:attrs
 
-    #[salsa::invoke(LangItems::lang_item_query)]
-    fn lang_item(&self, start_crate: Crate, item: LangItem) -> Option<LangItemTarget>;
-
     #[salsa::invoke(ImportMap::import_map_query)]
     fn import_map(&self, krate: Crate) -> Arc<ImportMap>;
 
@@ -349,9 +346,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
 
     // endregion:visibilities
 
-    #[salsa::invoke(LangItems::crate_lang_items_query)]
-    fn crate_lang_items(&self, krate: Crate) -> Option<Arc<LangItems>>;
-
     #[salsa::invoke(crate::lang_item::notable_traits_in_deps)]
     fn notable_traits_in_deps(&self, krate: Crate) -> Arc<[Arc<[TraitId]>]>;
     #[salsa::invoke(crate::lang_item::crate_notable_traits)]
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
index 5431ec9679c..6a4ac199b34 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs
@@ -83,104 +83,99 @@ impl LangItemTarget {
     }
 }
 
-#[derive(Default, Debug, Clone, PartialEq, Eq)]
-pub struct LangItems {
-    items: FxHashMap<LangItem, LangItemTarget>,
-}
+/// Salsa query. This will look for lang items in a specific crate.
+#[salsa::tracked(return_ref)]
+pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangItems>> {
+    let _p = tracing::info_span!("crate_lang_items_query").entered();
 
-impl LangItems {
-    pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
-        self.items.get(&item).copied()
-    }
+    let mut lang_items = LangItems::default();
 
-    /// Salsa query. This will look for lang items in a specific crate.
-    pub(crate) fn crate_lang_items_query(
-        db: &dyn DefDatabase,
-        krate: Crate,
-    ) -> Option<Arc<LangItems>> {
-        let _p = tracing::info_span!("crate_lang_items_query").entered();
-
-        let mut lang_items = LangItems::default();
+    let crate_def_map = db.crate_def_map(krate);
 
-        let crate_def_map = db.crate_def_map(krate);
+    for (_, module_data) in crate_def_map.modules() {
+        for impl_def in module_data.scope.impls() {
+            lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
+            for &(_, assoc) in db.impl_items(impl_def).items.iter() {
+                match assoc {
+                    AssocItemId::FunctionId(f) => {
+                        lang_items.collect_lang_item(db, f, LangItemTarget::Function)
+                    }
+                    AssocItemId::TypeAliasId(t) => {
+                        lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
+                    }
+                    AssocItemId::ConstId(_) => (),
+                }
+            }
+        }
 
-        for (_, module_data) in crate_def_map.modules() {
-            for impl_def in module_data.scope.impls() {
-                lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
-                for &(_, assoc) in db.impl_items(impl_def).items.iter() {
-                    match assoc {
+        for def in module_data.scope.declarations() {
+            match def {
+                ModuleDefId::TraitId(trait_) => {
+                    lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
+                    db.trait_items(trait_).items.iter().for_each(|&(_, assoc_id)| match assoc_id {
                         AssocItemId::FunctionId(f) => {
-                            lang_items.collect_lang_item(db, f, LangItemTarget::Function)
+                            lang_items.collect_lang_item(db, f, LangItemTarget::Function);
                         }
-                        AssocItemId::TypeAliasId(t) => {
-                            lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
+                        AssocItemId::TypeAliasId(alias) => {
+                            lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
                         }
-                        AssocItemId::ConstId(_) => (),
-                    }
+                        AssocItemId::ConstId(_) => {}
+                    });
                 }
-            }
-
-            for def in module_data.scope.declarations() {
-                match def {
-                    ModuleDefId::TraitId(trait_) => {
-                        lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
-                        db.trait_items(trait_).items.iter().for_each(
-                            |&(_, assoc_id)| match assoc_id {
-                                AssocItemId::FunctionId(f) => {
-                                    lang_items.collect_lang_item(db, f, LangItemTarget::Function);
-                                }
-                                AssocItemId::TypeAliasId(alias) => lang_items.collect_lang_item(
-                                    db,
-                                    alias,
-                                    LangItemTarget::TypeAlias,
-                                ),
-                                AssocItemId::ConstId(_) => {}
-                            },
-                        );
-                    }
-                    ModuleDefId::AdtId(AdtId::EnumId(e)) => {
-                        lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
-                        db.enum_variants(e).variants.iter().for_each(|&(id, _)| {
-                            lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
-                        });
-                    }
-                    ModuleDefId::AdtId(AdtId::StructId(s)) => {
-                        lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
-                    }
-                    ModuleDefId::AdtId(AdtId::UnionId(u)) => {
-                        lang_items.collect_lang_item(db, u, LangItemTarget::Union);
-                    }
-                    ModuleDefId::FunctionId(f) => {
-                        lang_items.collect_lang_item(db, f, LangItemTarget::Function);
-                    }
-                    ModuleDefId::StaticId(s) => {
-                        lang_items.collect_lang_item(db, s, LangItemTarget::Static);
-                    }
-                    ModuleDefId::TypeAliasId(t) => {
-                        lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
-                    }
-                    _ => {}
+                ModuleDefId::AdtId(AdtId::EnumId(e)) => {
+                    lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
+                    db.enum_variants(e).variants.iter().for_each(|&(id, _)| {
+                        lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
+                    });
+                }
+                ModuleDefId::AdtId(AdtId::StructId(s)) => {
+                    lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
+                }
+                ModuleDefId::AdtId(AdtId::UnionId(u)) => {
+                    lang_items.collect_lang_item(db, u, LangItemTarget::Union);
                 }
+                ModuleDefId::FunctionId(f) => {
+                    lang_items.collect_lang_item(db, f, LangItemTarget::Function);
+                }
+                ModuleDefId::StaticId(s) => {
+                    lang_items.collect_lang_item(db, s, LangItemTarget::Static);
+                }
+                ModuleDefId::TypeAliasId(t) => {
+                    lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
+                }
+                _ => {}
             }
         }
+    }
 
-        if lang_items.items.is_empty() { None } else { Some(Arc::new(lang_items)) }
+    if lang_items.items.is_empty() { None } else { Some(Box::new(lang_items)) }
+}
+
+/// Salsa query. Look for a lang item, starting from the specified crate and recursively
+/// traversing its dependencies.
+#[salsa::tracked]
+pub fn lang_item(
+    db: &dyn DefDatabase,
+    start_crate: Crate,
+    item: LangItem,
+) -> Option<LangItemTarget> {
+    let _p = tracing::info_span!("lang_item_query").entered();
+    if let Some(target) =
+        crate_lang_items(db, start_crate).as_ref().and_then(|it| it.items.get(&item).copied())
+    {
+        return Some(target);
     }
+    start_crate.data(db).dependencies.iter().find_map(|dep| lang_item(db, dep.crate_id, item))
+}
 
-    /// Salsa query. Look for a lang item, starting from the specified crate and recursively
-    /// traversing its dependencies.
-    pub(crate) fn lang_item_query(
-        db: &dyn DefDatabase,
-        start_crate: Crate,
-        item: LangItem,
-    ) -> Option<LangItemTarget> {
-        let _p = tracing::info_span!("lang_item_query").entered();
-        if let Some(target) =
-            db.crate_lang_items(start_crate).and_then(|it| it.items.get(&item).copied())
-        {
-            return Some(target);
-        }
-        start_crate.data(db).dependencies.iter().find_map(|dep| db.lang_item(dep.crate_id, item))
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
+pub struct LangItems {
+    items: FxHashMap<LangItem, LangItemTarget>,
+}
+
+impl LangItems {
+    pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
+        self.items.get(&item).copied()
     }
 
     fn collect_lang_item<T>(
@@ -269,18 +264,38 @@ macro_rules! language_item_table {
 }
 
 impl LangItem {
+    pub fn resolve_function(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<FunctionId> {
+        lang_item(db, start_crate, self).and_then(|t| t.as_function())
+    }
+
+    pub fn resolve_trait(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<TraitId> {
+        lang_item(db, start_crate, self).and_then(|t| t.as_trait())
+    }
+
+    pub fn resolve_enum(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<EnumId> {
+        lang_item(db, start_crate, self).and_then(|t| t.as_enum())
+    }
+
+    pub fn resolve_type_alias(
+        self,
+        db: &dyn DefDatabase,
+        start_crate: Crate,
+    ) -> Option<TypeAliasId> {
+        lang_item(db, start_crate, self).and_then(|t| t.as_type_alias())
+    }
+
     /// Opposite of [`LangItem::name`]
     pub fn from_name(name: &hir_expand::name::Name) -> Option<Self> {
         Self::from_symbol(name.symbol())
     }
 
     pub fn path(&self, db: &dyn DefDatabase, start_crate: Crate) -> Option<Path> {
-        let t = db.lang_item(start_crate, *self)?;
+        let t = lang_item(db, start_crate, *self)?;
         Some(Path::LangItem(t, None))
     }
 
     pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option<Path> {
-        let t = db.lang_item(start_crate, *self)?;
+        let t = lang_item(db, start_crate, *self)?;
         Some(Path::LangItem(t, Some(seg)))
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
index 71154454568..7acc9456ec9 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs
@@ -198,15 +198,13 @@ pub(crate) fn deref_by_trait(
         // blanked impl on `Deref`.
         #[expect(clippy::overly_complex_bool_expr)]
         if use_receiver_trait && false {
-            if let Some(receiver) =
-                db.lang_item(table.trait_env.krate, LangItem::Receiver).and_then(|l| l.as_trait())
-            {
+            if let Some(receiver) = LangItem::Receiver.resolve_trait(db, table.trait_env.krate) {
                 return Some(receiver);
             }
         }
         // Old rustc versions might not have `Receiver` trait.
         // Fallback to `Deref` if they don't
-        db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())
+        LangItem::Deref.resolve_trait(db, table.trait_env.krate)
     };
     let trait_id = trait_id()?;
     let target =
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
index 2aa9401eefa..376daccbdae 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_db.rs
@@ -16,7 +16,7 @@ use hir_def::{
     AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup,
     TypeAliasId, VariantId,
     hir::Movability,
-    lang_item::{LangItem, LangItemTarget},
+    lang_item::LangItem,
     signatures::{ImplFlags, StructFlags, TraitFlags},
 };
 
@@ -262,10 +262,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
         well_known_trait: rust_ir::WellKnownTrait,
     ) -> Option<chalk_ir::TraitId<Interner>> {
         let lang_attr = lang_item_from_well_known_trait(well_known_trait);
-        let trait_ = match self.db.lang_item(self.krate, lang_attr) {
-            Some(LangItemTarget::Trait(trait_)) => trait_,
-            _ => return None,
-        };
+        let trait_ = lang_attr.resolve_trait(self.db, self.krate)?;
         Some(to_chalk_trait_id(trait_))
     }
 
@@ -306,11 +303,8 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
                 chalk_ir::Binders::new(binders, bound)
             }
             crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
-                if let Some((future_trait, future_output)) = self
-                    .db
-                    .lang_item(self.krate, LangItem::Future)
-                    .and_then(|item| item.as_trait())
-                    .and_then(|trait_| {
+                if let Some((future_trait, future_output)) =
+                    LangItem::Future.resolve_trait(self.db, self.krate).and_then(|trait_| {
                         let alias = self
                             .db
                             .trait_items(trait_)
@@ -338,10 +332,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
                     });
                     let mut binder = vec![];
                     binder.push(crate::wrap_empty_binders(impl_bound));
-                    let sized_trait = self
-                        .db
-                        .lang_item(self.krate, LangItem::Sized)
-                        .and_then(|item| item.as_trait());
+                    let sized_trait = LangItem::Sized.resolve_trait(self.db, self.krate);
                     if let Some(sized_trait_) = sized_trait {
                         let sized_bound = WhereClause::Implemented(TraitRef {
                             trait_id: to_chalk_trait_id(sized_trait_),
@@ -660,9 +651,8 @@ pub(crate) fn associated_ty_data_query(
     }
 
     if !ctx.unsized_types.contains(&self_ty) {
-        let sized_trait = db
-            .lang_item(resolver.krate(), LangItem::Sized)
-            .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
+        let sized_trait =
+            LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id);
         let sized_bound = sized_trait.into_iter().map(|sized_trait| {
             let trait_bound =
                 rust_ir::TraitBound { trait_id: sized_trait, args_no_self: Default::default() };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
index 0f0cf6ae7ae..aabc4c4234d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
@@ -251,9 +251,7 @@ impl TyExt for Ty {
                 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
                     ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
                         let krate = def.module(db).krate();
-                        if let Some(future_trait) =
-                            db.lang_item(krate, LangItem::Future).and_then(|item| item.as_trait())
-                        {
+                        if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
                             // This is only used by type walking.
                             // Parameters will be walked outside, and projection predicate is not used.
                             // So just provide the Future trait.
@@ -364,8 +362,7 @@ impl TyExt for Ty {
 
     fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool {
         let crate_id = owner.module(db).krate();
-        let Some(copy_trait) = db.lang_item(crate_id, LangItem::Copy).and_then(|it| it.as_trait())
-        else {
+        let Some(copy_trait) = LangItem::Copy.resolve_trait(db, crate_id) else {
             return false;
         };
         let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(self).build();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index 5e3d8805896..57106412765 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -482,9 +482,8 @@ struct FilterMapNextChecker {
 impl FilterMapNextChecker {
     fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self {
         // Find and store the FunctionIds for Iterator::filter_map and Iterator::next
-        let (next_function_id, filter_map_function_id) = match db
-            .lang_item(resolver.krate(), LangItem::IteratorNext)
-            .and_then(|it| it.as_function())
+        let (next_function_id, filter_map_function_id) = match LangItem::IteratorNext
+            .resolve_function(db, resolver.krate())
         {
             Some(next_function_id) => (
                 Some(next_function_id),
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index f62e4bb4f80..e810467b994 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -19,7 +19,7 @@ use hir_def::{
     hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
     item_scope::ItemInNs,
     item_tree::FieldsShape,
-    lang_item::{LangItem, LangItemTarget},
+    lang_item::LangItem,
     nameres::DefMap,
     signatures::VariantFields,
     type_ref::{
@@ -1348,9 +1348,8 @@ impl HirDisplay for Ty {
                         )?;
                     }
                     ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
-                        let future_trait = db
-                            .lang_item(body.module(db).krate(), LangItem::Future)
-                            .and_then(LangItemTarget::as_trait);
+                        let future_trait =
+                            LangItem::Future.resolve_trait(db, body.module(db).krate());
                         let output = future_trait.and_then(|t| {
                             db.trait_items(t)
                                 .associated_type_by_name(&Name::new_symbol_root(sym::Output))
@@ -1728,9 +1727,7 @@ impl SizedByDefault {
         match self {
             Self::NotSized => false,
             Self::Sized { anchor } => {
-                let sized_trait = db
-                    .lang_item(anchor, LangItem::Sized)
-                    .and_then(|lang_item| lang_item.as_trait());
+                let sized_trait = LangItem::Sized.resolve_trait(db, anchor);
                 Some(trait_) == sized_trait
             }
         }
@@ -1895,8 +1892,7 @@ fn write_bounds_like_dyn_trait(
         write!(f, ">")?;
     }
     if let SizedByDefault::Sized { anchor } = default_sized {
-        let sized_trait =
-            f.db.lang_item(anchor, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
+        let sized_trait = LangItem::Sized.resolve_trait(f.db, anchor);
         if !is_sized {
             if !first {
                 write!(f, " + ")?;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
index 9823c854d5b..70763759ef0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs
@@ -19,9 +19,7 @@ fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool {
         AdtId::StructId(id) => db.lookup_intern_struct(id).container,
         AdtId::UnionId(id) => db.lookup_intern_union(id).container,
     };
-    let Some(drop_trait) =
-        db.lang_item(module.krate(), LangItem::Drop).and_then(|it| it.as_trait())
-    else {
+    let Some(drop_trait) = LangItem::Drop.resolve_trait(db, module.krate()) else {
         return false;
     };
     let impls = match module.containing_block() {
@@ -181,8 +179,7 @@ fn projection_has_drop_glue(
 }
 
 fn is_copy(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironment>) -> bool {
-    let Some(copy_trait) = db.lang_item(env.krate, LangItem::Copy).and_then(|it| it.as_trait())
-    else {
+    let Some(copy_trait) = LangItem::Copy.resolve_trait(db, env.krate) else {
         return false;
     };
     let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(ty).build();
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
index 80b18473907..fecaafb4c2e 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs
@@ -124,7 +124,7 @@ pub fn dyn_compatibility_of_trait_query(
 
 fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool {
     let krate = def.module(db).krate();
-    let Some(sized) = db.lang_item(krate, LangItem::Sized).and_then(|l| l.as_trait()) else {
+    let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else {
         return false;
     };
 
@@ -491,8 +491,8 @@ fn receiver_is_dispatchable(
 
     let krate = func.module(db).krate();
     let traits = (
-        db.lang_item(krate, LangItem::Unsize).and_then(|it| it.as_trait()),
-        db.lang_item(krate, LangItem::DispatchFromDyn).and_then(|it| it.as_trait()),
+        LangItem::Unsize.resolve_trait(db, krate),
+        LangItem::DispatchFromDyn.resolve_trait(db, krate),
     );
     let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else {
         return false;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index 790914fdaf2..f0ec31db8bb 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -39,7 +39,7 @@ use hir_def::{
     builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
     expr_store::{Body, ExpressionStore, HygieneId, path::Path},
     hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
-    lang_item::{LangItem, LangItemTarget},
+    lang_item::{LangItem, LangItemTarget, lang_item},
     layout::Integer,
     resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
     signatures::{ConstSignature, StaticSignature},
@@ -1801,7 +1801,7 @@ impl<'a> InferenceContext<'a> {
 
     fn resolve_lang_item(&self, item: LangItem) -> Option<LangItemTarget> {
         let krate = self.resolver.krate();
-        self.db.lang_item(krate, item)
+        lang_item(self.db, krate, item)
     }
 
     fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
index 847dd43a02d..39bd90849fe 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs
@@ -8,10 +8,7 @@
 use std::iter;
 
 use chalk_ir::{BoundVar, Goal, Mutability, TyKind, TyVariableKind, cast::Cast};
-use hir_def::{
-    hir::ExprId,
-    lang_item::{LangItem, LangItemTarget},
-};
+use hir_def::{hir::ExprId, lang_item::LangItem};
 use stdx::always;
 use triomphe::Arc;
 
@@ -701,8 +698,8 @@ impl InferenceTable<'_> {
             reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
 
         let krate = self.trait_env.krate;
-        let coerce_unsized_trait = match self.db.lang_item(krate, LangItem::CoerceUnsized) {
-            Some(LangItemTarget::Trait(trait_)) => trait_,
+        let coerce_unsized_trait = match LangItem::CoerceUnsized.resolve_trait(self.db, krate) {
+            Some(trait_) => trait_,
             _ => return Err(TypeError),
         };
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs
index cf0152ecd26..ac450c0b559 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs
@@ -126,10 +126,8 @@ impl InferenceContext<'_> {
             &Expr::Index { base, index } => {
                 if mutability == Mutability::Mut {
                     if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
-                        if let Some(index_trait) = self
-                            .db
-                            .lang_item(self.table.trait_env.krate, LangItem::IndexMut)
-                            .and_then(|l| l.as_trait())
+                        if let Some(index_trait) =
+                            LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate)
                         {
                             if let Some(index_fn) = self
                                 .db
@@ -183,10 +181,8 @@ impl InferenceContext<'_> {
                 let mut mutability = mutability;
                 if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
                     if mutability == Mutability::Mut {
-                        if let Some(deref_trait) = self
-                            .db
-                            .lang_item(self.table.trait_env.krate, LangItem::DerefMut)
-                            .and_then(|l| l.as_trait())
+                        if let Some(deref_trait) =
+                            LangItem::DerefMut.resolve_trait(self.db, self.table.trait_env.krate)
                         {
                             let ty = self.result.type_of_expr.get(*expr);
                             let is_mut_ptr = ty.is_some_and(|ty| {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
index 60aa9b5a17a..d921afeb987 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
@@ -1024,11 +1024,7 @@ impl<'a> InferenceTable<'a> {
             }
         }
 
-        let Some(sized) = self
-            .db
-            .lang_item(self.trait_env.krate, LangItem::Sized)
-            .and_then(|sized| sized.as_trait())
-        else {
+        let Some(sized) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else {
             return false;
         };
         let sized_pred = WhereClause::Implemented(TraitRef {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index e4688d044e9..6d7e58bea6a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -590,10 +590,7 @@ impl<'a> TyLoweringContext<'a> {
                 }
             }
             &TypeBound::Path(path, TraitBoundModifier::Maybe) => {
-                let sized_trait = self
-                    .db
-                    .lang_item(self.resolver.krate(), LangItem::Sized)
-                    .and_then(|lang_item| lang_item.as_trait());
+                let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate());
                 // Don't lower associated type bindings as the only possible relaxed trait bound
                 // `?Sized` has no of them.
                 // If we got another trait here ignore the bound completely.
@@ -736,10 +733,8 @@ impl<'a> TyLoweringContext<'a> {
             }
 
             if !ctx.unsized_types.contains(&self_ty) {
-                let sized_trait = ctx
-                    .db
-                    .lang_item(krate, LangItem::Sized)
-                    .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
+                let sized_trait =
+                    LangItem::Sized.resolve_trait(ctx.db, krate).map(to_chalk_trait_id);
                 let sized_clause = sized_trait.map(|trait_id| {
                     let clause = WhereClause::Implemented(TraitRef {
                         trait_id,
@@ -1188,9 +1183,7 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>(
     substitution: &'subst Substitution,
     resolver: &Resolver,
 ) -> Option<impl Iterator<Item = WhereClause> + Captures<'a> + Captures<'subst>> {
-    let sized_trait = db
-        .lang_item(resolver.krate(), LangItem::Sized)
-        .and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id))?;
+    let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id)?;
 
     let trait_self_idx = trait_self_param_idx(db, def);
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index 386226b16d5..286381ce99c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -655,22 +655,15 @@ impl Evaluator<'_> {
             mir_or_dyn_index_cache: RefCell::new(Default::default()),
             unused_locals_store: RefCell::new(Default::default()),
             cached_ptr_size,
-            cached_fn_trait_func: db
-                .lang_item(crate_id, LangItem::Fn)
-                .and_then(|x| x.as_trait())
+            cached_fn_trait_func: LangItem::Fn
+                .resolve_trait(db, crate_id)
                 .and_then(|x| db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call))),
-            cached_fn_mut_trait_func: db
-                .lang_item(crate_id, LangItem::FnMut)
-                .and_then(|x| x.as_trait())
-                .and_then(|x| {
-                    db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut))
-                }),
-            cached_fn_once_trait_func: db
-                .lang_item(crate_id, LangItem::FnOnce)
-                .and_then(|x| x.as_trait())
-                .and_then(|x| {
-                    db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once))
-                }),
+            cached_fn_mut_trait_func: LangItem::FnMut.resolve_trait(db, crate_id).and_then(|x| {
+                db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut))
+            }),
+            cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| {
+                db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once))
+            }),
         })
     }
 
@@ -2811,7 +2804,7 @@ impl Evaluator<'_> {
         span: MirSpan,
     ) -> Result<()> {
         let Some(drop_fn) = (|| {
-            let drop_trait = self.db.lang_item(self.crate_id, LangItem::Drop)?.as_trait()?;
+            let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?;
             self.db.trait_items(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop))
         })() else {
             // in some tests we don't have drop trait in minicore, and
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index 4de44cfd02e..26ef95d264b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -6,7 +6,6 @@ use std::cmp::{self, Ordering};
 use chalk_ir::TyKind;
 use hir_def::{
     builtin_type::{BuiltinInt, BuiltinUint},
-    lang_item::LangItemTarget,
     resolver::HasResolver,
 };
 use hir_expand::name::Name;
@@ -156,8 +155,8 @@ impl Evaluator<'_> {
         if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
             let resolver = self.db.crate_def_map(self.crate_id).crate_root().resolver(self.db);
 
-            let Some(hir_def::lang_item::LangItemTarget::Function(const_panic_fmt)) =
-                self.db.lang_item(resolver.krate(), LangItem::ConstPanicFmt)
+            let Some(const_panic_fmt) =
+                LangItem::ConstPanicFmt.resolve_function(self.db, resolver.krate())
             else {
                 not_supported!("const_panic_fmt lang item not found or not a function");
             };
@@ -1257,12 +1256,12 @@ impl Evaluator<'_> {
                     let addr = tuple.interval.addr.offset(offset);
                     args.push(IntervalAndTy::new(addr, field, self, locals)?);
                 }
-                if let Some(target) = self.db.lang_item(self.crate_id, LangItem::FnOnce) {
-                    if let Some(def) = target.as_trait().and_then(|it| {
-                        self.db
-                            .trait_items(it)
-                            .method_by_name(&Name::new_symbol_root(sym::call_once))
-                    }) {
+                if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) {
+                    if let Some(def) = self
+                        .db
+                        .trait_items(target)
+                        .method_by_name(&Name::new_symbol_root(sym::call_once))
+                    {
                         self.exec_fn_trait(
                             def,
                             &args,
@@ -1376,9 +1375,7 @@ impl Evaluator<'_> {
                         }
                     }
                 }
-                if let Some(LangItemTarget::EnumId(e)) =
-                    self.db.lang_item(self.crate_id, LangItem::Ordering)
-                {
+                if let Some(e) = LangItem::Ordering.resolve_enum(self.db, self.crate_id) {
                     let ty = self.db.ty(e.into());
                     let r = self
                         .compute_discriminant(ty.skip_binders().clone(), &[result as i8 as u8])?;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index 557027756f3..ebccb11ce0c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -13,7 +13,7 @@ use hir_def::{
         Pat, PatId, RecordFieldPat, RecordLitField,
     },
     item_tree::FieldsShape,
-    lang_item::{LangItem, LangItemTarget},
+    lang_item::{LangItem, LangItemTarget, lang_item},
     resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
 };
 use hir_expand::name::Name;
@@ -1727,7 +1727,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
 
     fn resolve_lang_item(&self, item: LangItem) -> Result<LangItemTarget> {
         let crate_id = self.owner.module(self.db).krate();
-        self.db.lang_item(crate_id, item).ok_or(MirLowerError::LangItemNotFound(item))
+        lang_item(self.db, crate_id, item).ok_or(MirLowerError::LangItemNotFound(item))
     }
 
     fn lower_block_to_place(
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
index a5c195d4086..f9f8776cff7 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs
@@ -8,10 +8,7 @@ use chalk_recursive::Cache;
 use chalk_solve::{Solver, logging_db::LoggingRustIrDatabase, rust_ir};
 
 use base_db::Crate;
-use hir_def::{
-    BlockId, TraitId,
-    lang_item::{LangItem, LangItemTarget},
-};
+use hir_def::{BlockId, TraitId, lang_item::LangItem};
 use hir_expand::name::Name;
 use intern::sym;
 use span::Edition;
@@ -292,10 +289,6 @@ impl FnTrait {
     }
 
     pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<TraitId> {
-        let target = db.lang_item(krate, self.lang_item())?;
-        match target {
-            LangItemTarget::Trait(t) => Some(t),
-            _ => None,
-        }
+        self.lang_item().resolve_trait(db, krate)
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
index 198f715a6db..1e0ff423ded 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs
@@ -36,8 +36,7 @@ use crate::{
 pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator<Item = TraitId> + '_ {
     [LangItem::Fn, LangItem::FnMut, LangItem::FnOnce]
         .into_iter()
-        .filter_map(move |lang| db.lang_item(krate, lang))
-        .flat_map(|it| it.as_trait())
+        .filter_map(move |lang| lang.resolve_trait(db, krate))
 }
 
 /// Returns an iterator over the direct super traits (including the trait itself).
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 53817f37aa6..124ab8e274a 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -516,8 +516,7 @@ impl HirDisplay for TypeParam {
             return Ok(());
         }
 
-        let sized_trait =
-            f.db.lang_item(krate, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
+        let sized_trait = LangItem::Sized.resolve_trait(f.db, krate);
         let has_only_sized_bound = predicates.iter().all(move |pred| match pred.skip_binders() {
             WhereClause::Implemented(it) => Some(it.hir_trait_id()) == sized_trait,
             _ => false,
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 143c13069e4..c62e4cf4497 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -53,7 +53,6 @@ use hir_def::{
         generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
     },
     item_tree::{AttrOwner, FieldParent, ImportAlias, ItemTreeFieldId, ItemTreeNode},
-    lang_item::LangItemTarget,
     layout::{self, ReprOptions, TargetDataLayout},
     nameres::{self, diagnostics::DefDiagnostic},
     per_ns::PerNs,
@@ -781,7 +780,7 @@ impl Module {
             let drop_maybe_dangle = (|| {
                 // FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper
                 let trait_ = trait_?;
-                let drop_trait = db.lang_item(self.krate().into(), LangItem::Drop)?.as_trait()?;
+                let drop_trait = LangItem::Drop.resolve_trait(db, self.krate().into())?;
                 if drop_trait != trait_.into() {
                     return None;
                 }
@@ -2388,14 +2387,11 @@ impl Function {
         }
 
         let Some(impl_traits) = self.ret_type(db).as_impl_traits(db) else { return false };
-        let Some(future_trait_id) =
-            db.lang_item(self.ty(db).env.krate, LangItem::Future).and_then(|t| t.as_trait())
+        let Some(future_trait_id) = LangItem::Future.resolve_trait(db, self.ty(db).env.krate)
         else {
             return false;
         };
-        let Some(sized_trait_id) =
-            db.lang_item(self.ty(db).env.krate, LangItem::Sized).and_then(|t| t.as_trait())
-        else {
+        let Some(sized_trait_id) = LangItem::Sized.resolve_trait(db, self.ty(db).env.krate) else {
             return false;
         };
 
@@ -2861,9 +2857,7 @@ pub struct Trait {
 
 impl Trait {
     pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
-        db.lang_item(krate.into(), LangItem::from_name(name)?)
-            .and_then(LangItemTarget::as_trait)
-            .map(Into::into)
+        LangItem::from_name(name)?.resolve_trait(db, krate.into()).map(Into::into)
     }
 
     pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -4989,18 +4983,14 @@ impl Type {
     /// `std::future::Future` and returns the `Output` associated type.
     /// This function is used in `.await` syntax completion.
     pub fn into_future_output(&self, db: &dyn HirDatabase) -> Option<Type> {
-        let trait_ = db
-            .lang_item(self.env.krate, LangItem::IntoFutureIntoFuture)
-            .and_then(|it| {
-                let into_future_fn = it.as_function()?;
+        let trait_ = LangItem::IntoFutureIntoFuture
+            .resolve_function(db, self.env.krate)
+            .and_then(|into_future_fn| {
                 let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
                 let into_future_trait = assoc_item.container_or_implemented_trait(db)?;
                 Some(into_future_trait.id)
             })
-            .or_else(|| {
-                let future_trait = db.lang_item(self.env.krate, LangItem::Future)?;
-                future_trait.as_trait()
-            })?;
+            .or_else(|| LangItem::Future.resolve_trait(db, self.env.krate))?;
 
         let canonical_ty =
             Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
@@ -5015,14 +5005,13 @@ impl Type {
 
     /// This does **not** resolve `IntoFuture`, only `Future`.
     pub fn future_output(self, db: &dyn HirDatabase) -> Option<Type> {
-        let future_output =
-            db.lang_item(self.env.krate, LangItem::FutureOutput)?.as_type_alias()?;
+        let future_output = LangItem::FutureOutput.resolve_type_alias(db, self.env.krate)?;
         self.normalize_trait_assoc_type(db, &[], future_output.into())
     }
 
     /// This does **not** resolve `IntoIterator`, only `Iterator`.
     pub fn iterator_item(self, db: &dyn HirDatabase) -> Option<Type> {
-        let iterator_trait = db.lang_item(self.env.krate, LangItem::Iterator)?.as_trait()?;
+        let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
         let iterator_item = db
             .trait_items(iterator_trait)
             .associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
@@ -5030,9 +5019,7 @@ impl Type {
     }
 
     pub fn impls_iterator(self, db: &dyn HirDatabase) -> bool {
-        let Some(iterator_trait) =
-            db.lang_item(self.env.krate, LangItem::Iterator).and_then(|it| it.as_trait())
-        else {
+        let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else {
             return false;
         };
         let canonical_ty =
@@ -5042,12 +5029,13 @@ impl Type {
 
     /// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
     pub fn into_iterator_iter(self, db: &dyn HirDatabase) -> Option<Type> {
-        let trait_ = db.lang_item(self.env.krate, LangItem::IntoIterIntoIter).and_then(|it| {
-            let into_iter_fn = it.as_function()?;
-            let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
-            let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
-            Some(into_iter_trait.id)
-        })?;
+        let trait_ = LangItem::IntoIterIntoIter.resolve_function(db, self.env.krate).and_then(
+            |into_iter_fn| {
+                let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
+                let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
+                Some(into_iter_trait.id)
+            },
+        )?;
 
         let canonical_ty =
             Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
@@ -5133,10 +5121,8 @@ impl Type {
     }
 
     pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
-        let lang_item = db.lang_item(self.env.krate, LangItem::Copy);
-        let copy_trait = match lang_item {
-            Some(LangItemTarget::Trait(it)) => it,
-            _ => return false,
+        let Some(copy_trait) = LangItem::Copy.resolve_trait(db, self.env.krate) else {
+            return false;
         };
         self.impls_trait(db, copy_trait.into(), &[])
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index 666efe8ec64..7d447116e08 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -556,8 +556,8 @@ impl SourceAnalyzer {
             }
         }
 
-        let future_trait = db.lang_item(self.resolver.krate(), LangItem::Future)?.as_trait()?;
-        let poll_fn = db.lang_item(self.resolver.krate(), LangItem::FuturePoll)?.as_function()?;
+        let future_trait = LangItem::Future.resolve_trait(db, self.resolver.krate())?;
+        let poll_fn = LangItem::FuturePoll.resolve_function(db, self.resolver.krate())?;
         // HACK: subst for `poll()` coincides with that for `Future` because `poll()` itself
         // doesn't have any generic parameters, so we skip building another subst for `poll()`.
         let substs = hir_ty::TyBuilder::subst_for_def(db, future_trait, None).push(ty).build();
@@ -666,7 +666,7 @@ impl SourceAnalyzer {
     ) -> Option<FunctionId> {
         let ty = self.ty_of_expr(try_expr.expr()?)?;
 
-        let op_fn = db.lang_item(self.resolver.krate(), LangItem::TryTraitBranch)?.as_function()?;
+        let op_fn = LangItem::TryTraitBranch.resolve_function(db, self.resolver.krate())?;
         let op_trait = match op_fn.lookup(db).container {
             ItemContainerId::TraitId(id) => id,
             _ => return None,
@@ -1425,7 +1425,7 @@ impl SourceAnalyzer {
         lang_trait: LangItem,
         method_name: &Name,
     ) -> Option<(TraitId, FunctionId)> {
-        let trait_id = db.lang_item(self.resolver.krate(), lang_trait)?.as_trait()?;
+        let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?;
         let fn_id = db.trait_items(trait_id).method_by_name(method_name)?;
         Some((trait_id, fn_id))
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 2f2d2252f84..075afcec019 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -634,9 +634,7 @@ fn walk_and_push_ty(
         } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
             push_new_def(trait_.into());
         } else if let Some(tp) = t.as_type_param(db) {
-            let sized_trait = db
-                .lang_item(t.krate(db).into(), LangItem::Sized)
-                .and_then(|lang_item| lang_item.as_trait());
+            let sized_trait = LangItem::Sized.resolve_trait(db, t.krate(db).into());
             tp.trait_bounds(db)
                 .into_iter()
                 .filter(|&it| Some(it.into()) != sized_trait)