Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/attr.rs5
-rw-r--r--crates/hir-def/src/db.rs5
-rw-r--r--crates/hir-def/src/expr_store/lower.rs115
-rw-r--r--crates/hir-def/src/expr_store/pretty.rs16
-rw-r--r--crates/hir-def/src/lang_item.rs575
-rw-r--r--crates/hir-def/src/resolver.rs48
-rw-r--r--crates/hir-def/src/signatures.rs11
-rw-r--r--crates/hir-ty/src/autoderef.rs24
-rw-r--r--crates/hir-ty/src/diagnostics/expr.rs10
-rw-r--r--crates/hir-ty/src/display.rs27
-rw-r--r--crates/hir-ty/src/drop.rs12
-rw-r--r--crates/hir-ty/src/dyn_compatibility.rs15
-rw-r--r--crates/hir-ty/src/infer.rs32
-rw-r--r--crates/hir-ty/src/infer/closure.rs34
-rw-r--r--crates/hir-ty/src/infer/coerce.rs7
-rw-r--r--crates/hir-ty/src/infer/expr.rs15
-rw-r--r--crates/hir-ty/src/infer/mutability.rs2
-rw-r--r--crates/hir-ty/src/infer/op.rs13
-rw-r--r--crates/hir-ty/src/infer/place_op.rs16
-rw-r--r--crates/hir-ty/src/infer/unify.rs12
-rw-r--r--crates/hir-ty/src/lang_items.rs59
-rw-r--r--crates/hir-ty/src/lib.rs10
-rw-r--r--crates/hir-ty/src/lower.rs53
-rw-r--r--crates/hir-ty/src/method_resolution/confirm.rs9
-rw-r--r--crates/hir-ty/src/mir/eval.rs18
-rw-r--r--crates/hir-ty/src/mir/eval/shim.rs49
-rw-r--r--crates/hir-ty/src/mir/lower.rs16
-rw-r--r--crates/hir-ty/src/mir/lower/as_place.rs25
-rw-r--r--crates/hir-ty/src/next_solver/infer/mod.rs5
-rw-r--r--crates/hir-ty/src/next_solver/interner.rs270
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs3
-rw-r--r--crates/hir-ty/src/tests/incremental.rs26
-rw-r--r--crates/hir-ty/src/traits.rs61
-rw-r--r--crates/hir-ty/src/utils.rs13
-rw-r--r--crates/hir/src/display.rs3
-rw-r--r--crates/hir/src/lib.rs127
-rw-r--r--crates/hir/src/source_analyzer.rs38
-rw-r--r--crates/ide-completion/src/tests/flyimport.rs2
-rw-r--r--crates/ide/src/hover.rs8
-rw-r--r--crates/ide/src/hover/render.rs4
40 files changed, 879 insertions, 914 deletions
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index b4fcfa11ae..6d3005e01c 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -27,7 +27,6 @@ use crate::{
VariantId,
db::DefDatabase,
item_tree::block_item_tree_query,
- lang_item::LangItem,
nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource},
};
@@ -209,8 +208,8 @@ impl Attrs {
}
#[inline]
- pub fn lang_item(&self) -> Option<LangItem> {
- self.by_key(sym::lang).string_value().and_then(LangItem::from_symbol)
+ pub fn lang_item(&self) -> Option<&Symbol> {
+ self.by_key(sym::lang).string_value()
}
#[inline]
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index 49aafb2b86..d6bba6306b 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -24,7 +24,6 @@ use crate::{
hir::generics::GenericParams,
import_map::ImportMap,
item_tree::{ItemTree, file_item_tree_query},
- lang_item::{self, LangItem},
nameres::crate_def_map,
signatures::{
ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
@@ -254,10 +253,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
#[salsa::invoke_interned(AttrsWithOwner::attrs_query)]
fn attrs(&self, def: AttrDefId) -> Attrs;
- #[salsa::transparent]
- #[salsa::invoke(lang_item::lang_attr)]
- fn lang_attr(&self, def: AttrDefId) -> Option<LangItem>;
-
// endregion:attrs
#[salsa::invoke(ImportMap::import_map_query)]
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index e3bfc5b753..238538dc58 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -5,7 +5,7 @@ mod asm;
mod generics;
mod path;
-use std::mem;
+use std::{cell::OnceCell, mem};
use base_db::FxIndexSet;
use cfg::CfgOptions;
@@ -57,7 +57,7 @@ use crate::{
},
item_scope::BuiltinShadowMode,
item_tree::FieldsShape,
- lang_item::LangItem,
+ lang_item::{LangItemTarget, LangItems},
nameres::{DefMap, LocalDefMap, MacroSubNs, block_def_map},
type_ref::{
ArrayType, ConstRef, FnType, LifetimeRef, LifetimeRefId, Mutability, PathId, Rawness,
@@ -416,6 +416,7 @@ pub struct ExprCollector<'db> {
def_map: &'db DefMap,
local_def_map: &'db LocalDefMap,
module: ModuleId,
+ lang_items: OnceCell<&'db LangItems>,
pub store: ExpressionStoreBuilder,
// state stuff
@@ -513,7 +514,7 @@ impl BindingList {
}
}
-impl ExprCollector<'_> {
+impl<'db> ExprCollector<'db> {
pub fn new(
db: &dyn DefDatabase,
module: ModuleId,
@@ -527,6 +528,7 @@ impl ExprCollector<'_> {
module,
def_map,
local_def_map,
+ lang_items: OnceCell::new(),
store: ExpressionStoreBuilder::default(),
expander,
current_try_block_label: None,
@@ -540,6 +542,11 @@ impl ExprCollector<'_> {
}
#[inline]
+ pub(crate) fn lang_items(&self) -> &'db LangItems {
+ self.lang_items.get_or_init(|| crate::lang_item::lang_items(self.db, self.module.krate))
+ }
+
+ #[inline]
pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
self.expander.span_map()
}
@@ -1654,7 +1661,7 @@ impl ExprCollector<'_> {
/// `try { <stmts>; }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(()) }`
/// and save the `<new_label>` to use it as a break target for desugaring of the `?` operator.
fn desugar_try_block(&mut self, e: BlockExpr) -> ExprId {
- let try_from_output = self.lang_path(LangItem::TryTraitFromOutput);
+ let try_from_output = self.lang_path(self.lang_items().TryTraitFromOutput);
let label = self.alloc_label_desugared(Label {
name: Name::generate_new_name(self.store.labels.len()),
});
@@ -1753,10 +1760,11 @@ impl ExprCollector<'_> {
/// }
/// ```
fn collect_for_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::ForExpr) -> ExprId {
- let into_iter_fn = self.lang_path(LangItem::IntoIterIntoIter);
- let iter_next_fn = self.lang_path(LangItem::IteratorNext);
- let option_some = self.lang_path(LangItem::OptionSome);
- let option_none = self.lang_path(LangItem::OptionNone);
+ let lang_items = self.lang_items();
+ let into_iter_fn = self.lang_path(lang_items.IntoIterIntoIter);
+ let iter_next_fn = self.lang_path(lang_items.IteratorNext);
+ let option_some = self.lang_path(lang_items.OptionSome);
+ let option_none = self.lang_path(lang_items.OptionNone);
let head = self.collect_expr_opt(e.iterable());
let into_iter_fn_expr =
self.alloc_expr(into_iter_fn.map_or(Expr::Missing, Expr::Path), syntax_ptr);
@@ -1836,10 +1844,11 @@ impl ExprCollector<'_> {
/// }
/// ```
fn collect_try_operator(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::TryExpr) -> ExprId {
- let try_branch = self.lang_path(LangItem::TryTraitBranch);
- let cf_continue = self.lang_path(LangItem::ControlFlowContinue);
- let cf_break = self.lang_path(LangItem::ControlFlowBreak);
- let try_from_residual = self.lang_path(LangItem::TryTraitFromResidual);
+ let lang_items = self.lang_items();
+ let try_branch = self.lang_path(lang_items.TryTraitBranch);
+ let cf_continue = self.lang_path(lang_items.ControlFlowContinue);
+ let cf_break = self.lang_path(lang_items.ControlFlowBreak);
+ let try_from_residual = self.lang_path(lang_items.TryTraitFromResidual);
let operand = self.collect_expr_opt(e.expr());
let try_branch = self.alloc_expr(try_branch.map_or(Expr::Missing, Expr::Path), syntax_ptr);
let expr = self
@@ -2773,11 +2782,10 @@ impl ExprCollector<'_> {
// Assume that rustc version >= 1.89.0 iff lang item `format_arguments` exists
// but `format_unsafe_arg` does not
- let fmt_args =
- || crate::lang_item::lang_item(self.db, self.module.krate(), LangItem::FormatArguments);
- let fmt_unsafe_arg =
- || crate::lang_item::lang_item(self.db, self.module.krate(), LangItem::FormatUnsafeArg);
- let use_format_args_since_1_89_0 = fmt_args().is_some() && fmt_unsafe_arg().is_none();
+ let lang_items = self.lang_items();
+ let fmt_args = lang_items.FormatArguments;
+ let fmt_unsafe_arg = lang_items.FormatUnsafeArg;
+ let use_format_args_since_1_89_0 = fmt_args.is_some() && fmt_unsafe_arg.is_none();
let idx = if use_format_args_since_1_89_0 {
self.collect_format_args_impl(syntax_ptr, fmt, argmap, lit_pieces, format_options)
@@ -2856,16 +2864,13 @@ impl ExprCollector<'_> {
// unsafe { ::core::fmt::UnsafeArg::new() }
// )
- let new_v1_formatted = LangItem::FormatArguments.ty_rel_path(
- self.db,
- self.module.krate(),
+ let lang_items = self.lang_items();
+ let new_v1_formatted = self.ty_rel_lang_path(
+ lang_items.FormatArguments,
Name::new_symbol_root(sym::new_v1_formatted),
);
- let unsafe_arg_new = LangItem::FormatUnsafeArg.ty_rel_path(
- self.db,
- self.module.krate(),
- Name::new_symbol_root(sym::new),
- );
+ let unsafe_arg_new =
+ self.ty_rel_lang_path(lang_items.FormatUnsafeArg, Name::new_symbol_root(sym::new));
let new_v1_formatted =
self.alloc_expr_desugared(new_v1_formatted.map_or(Expr::Missing, Expr::Path));
@@ -3044,9 +3049,8 @@ impl ExprCollector<'_> {
// )
// }
- let new_v1_formatted = LangItem::FormatArguments.ty_rel_path(
- self.db,
- self.module.krate(),
+ let new_v1_formatted = self.ty_rel_lang_path(
+ self.lang_items().FormatArguments,
Name::new_symbol_root(sym::new_v1_formatted),
);
let new_v1_formatted =
@@ -3099,6 +3103,7 @@ impl ExprCollector<'_> {
placeholder: &FormatPlaceholder,
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
) -> ExprId {
+ let lang_items = self.lang_items();
let position = match placeholder.argument.index {
Ok(arg_index) => {
let (i, _) =
@@ -3159,15 +3164,14 @@ impl ExprCollector<'_> {
let width =
RecordLitField { name: Name::new_symbol_root(sym::width), expr: width_expr };
self.alloc_expr_desugared(Expr::RecordLit {
- path: LangItem::FormatPlaceholder.path(self.db, self.module.krate()).map(Box::new),
+ path: self.lang_path(lang_items.FormatPlaceholder).map(Box::new),
fields: Box::new([position, flags, precision, width]),
spread: None,
})
} else {
let format_placeholder_new = {
- let format_placeholder_new = LangItem::FormatPlaceholder.ty_rel_path(
- self.db,
- self.module.krate(),
+ let format_placeholder_new = self.ty_rel_lang_path(
+ lang_items.FormatPlaceholder,
Name::new_symbol_root(sym::new),
);
match format_placeholder_new {
@@ -3188,9 +3192,8 @@ impl ExprCollector<'_> {
)));
let fill = self.alloc_expr_desugared(Expr::Literal(Literal::Char(fill.unwrap_or(' '))));
let align = {
- let align = LangItem::FormatAlignment.ty_rel_path(
- self.db,
- self.module.krate(),
+ let align = self.ty_rel_lang_path(
+ lang_items.FormatAlignment,
match alignment {
Some(FormatAlignment::Left) => Name::new_symbol_root(sym::Left),
Some(FormatAlignment::Right) => Name::new_symbol_root(sym::Right),
@@ -3234,6 +3237,7 @@ impl ExprCollector<'_> {
count: &Option<FormatCount>,
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
) -> ExprId {
+ let lang_items = self.lang_items();
match count {
Some(FormatCount::Literal(n)) => {
let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
@@ -3241,11 +3245,9 @@ impl ExprCollector<'_> {
// FIXME: Change this to Some(BuiltinUint::U16) once we drop support for toolchains < 1.88
None,
)));
- let count_is = match LangItem::FormatCount.ty_rel_path(
- self.db,
- self.module.krate(),
- Name::new_symbol_root(sym::Is),
- ) {
+ let count_is = match self
+ .ty_rel_lang_path(lang_items.FormatCount, Name::new_symbol_root(sym::Is))
+ {
Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)),
None => self.missing_expr(),
};
@@ -3259,11 +3261,9 @@ impl ExprCollector<'_> {
i as u128,
Some(BuiltinUint::Usize),
)));
- let count_param = match LangItem::FormatCount.ty_rel_path(
- self.db,
- self.module.krate(),
- Name::new_symbol_root(sym::Param),
- ) {
+ let count_param = match self
+ .ty_rel_lang_path(lang_items.FormatCount, Name::new_symbol_root(sym::Param))
+ {
Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
None => self.missing_expr(),
};
@@ -3277,11 +3277,9 @@ impl ExprCollector<'_> {
self.missing_expr()
}
}
- None => match LangItem::FormatCount.ty_rel_path(
- self.db,
- self.module.krate(),
- Name::new_symbol_root(sym::Implied),
- ) {
+ None => match self
+ .ty_rel_lang_path(lang_items.FormatCount, Name::new_symbol_root(sym::Implied))
+ {
Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
None => self.missing_expr(),
},
@@ -3299,9 +3297,8 @@ impl ExprCollector<'_> {
use ArgumentType::*;
use FormatTrait::*;
- let new_fn = match LangItem::FormatArgument.ty_rel_path(
- self.db,
- self.module.krate(),
+ let new_fn = match self.ty_rel_lang_path(
+ self.lang_items().FormatArgument,
Name::new_symbol_root(match ty {
Format(Display) => sym::new_display,
Format(Debug) => sym::new_debug,
@@ -3323,8 +3320,16 @@ impl ExprCollector<'_> {
// endregion: format
- fn lang_path(&self, lang: LangItem) -> Option<Path> {
- lang.path(self.db, self.module.krate())
+ fn lang_path(&self, lang: Option<impl Into<LangItemTarget>>) -> Option<Path> {
+ Some(Path::LangItem(lang?.into(), None))
+ }
+
+ fn ty_rel_lang_path(
+ &self,
+ lang: Option<impl Into<LangItemTarget>>,
+ relative_name: Name,
+ ) -> Option<Path> {
+ Some(Path::LangItem(lang?.into(), Some(relative_name)))
}
}
diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs
index 4ba70938d0..42d3e07d9c 100644
--- a/crates/hir-def/src/expr_store/pretty.rs
+++ b/crates/hir-def/src/expr_store/pretty.rs
@@ -1091,15 +1091,15 @@ impl Printer<'_> {
}};
}
match *it {
- LangItemTarget::ImplDef(it) => w!(self, "{it:?}"),
+ LangItemTarget::ImplId(it) => w!(self, "{it:?}"),
LangItemTarget::EnumId(it) => write_name!(it),
- LangItemTarget::Function(it) => write_name!(it),
- LangItemTarget::Static(it) => write_name!(it),
- LangItemTarget::Struct(it) => write_name!(it),
- LangItemTarget::Union(it) => write_name!(it),
- LangItemTarget::TypeAlias(it) => write_name!(it),
- LangItemTarget::Trait(it) => write_name!(it),
- LangItemTarget::EnumVariant(it) => write_name!(it),
+ LangItemTarget::FunctionId(it) => write_name!(it),
+ LangItemTarget::StaticId(it) => write_name!(it),
+ LangItemTarget::StructId(it) => write_name!(it),
+ LangItemTarget::UnionId(it) => write_name!(it),
+ LangItemTarget::TypeAliasId(it) => write_name!(it),
+ LangItemTarget::TraitId(it) => write_name!(it),
+ LangItemTarget::EnumVariantId(it) => write_name!(it),
}
if let Some(s) = s {
diff --git a/crates/hir-def/src/lang_item.rs b/crates/hir-def/src/lang_item.rs
index 91a90f6d84..e634a95b67 100644
--- a/crates/hir-def/src/lang_item.rs
+++ b/crates/hir-def/src/lang_item.rs
@@ -2,101 +2,36 @@
//!
//! This attribute to tell the compiler about semi built-in std library
//! features, such as Fn family of traits.
-use hir_expand::name::Name;
use intern::{Symbol, sym};
-use rustc_hash::FxHashMap;
+use stdx::impl_from;
use crate::{
AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId,
StaticId, StructId, TraitId, TypeAliasId, UnionId,
db::DefDatabase,
- expr_store::path::Path,
nameres::{assoc::TraitItems, crate_def_map, crate_local_def_map},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LangItemTarget {
EnumId(EnumId),
- Function(FunctionId),
- ImplDef(ImplId),
- Static(StaticId),
- Struct(StructId),
- Union(UnionId),
- TypeAlias(TypeAliasId),
- Trait(TraitId),
- EnumVariant(EnumVariantId),
+ FunctionId(FunctionId),
+ ImplId(ImplId),
+ StaticId(StaticId),
+ StructId(StructId),
+ UnionId(UnionId),
+ TypeAliasId(TypeAliasId),
+ TraitId(TraitId),
+ EnumVariantId(EnumVariantId),
}
-impl LangItemTarget {
- pub fn as_enum(self) -> Option<EnumId> {
- match self {
- LangItemTarget::EnumId(id) => Some(id),
- _ => None,
- }
- }
-
- pub fn as_function(self) -> Option<FunctionId> {
- match self {
- LangItemTarget::Function(id) => Some(id),
- _ => None,
- }
- }
-
- pub fn as_impl_def(self) -> Option<ImplId> {
- match self {
- LangItemTarget::ImplDef(id) => Some(id),
- _ => None,
- }
- }
-
- pub fn as_static(self) -> Option<StaticId> {
- match self {
- LangItemTarget::Static(id) => Some(id),
- _ => None,
- }
- }
-
- pub fn as_struct(self) -> Option<StructId> {
- match self {
- LangItemTarget::Struct(id) => Some(id),
- _ => None,
- }
- }
-
- pub fn as_trait(self) -> Option<TraitId> {
- match self {
- LangItemTarget::Trait(id) => Some(id),
- _ => None,
- }
- }
-
- pub fn as_enum_variant(self) -> Option<EnumVariantId> {
- match self {
- LangItemTarget::EnumVariant(id) => Some(id),
- _ => None,
- }
- }
-
- pub fn as_type_alias(self) -> Option<TypeAliasId> {
- match self {
- LangItemTarget::TypeAlias(id) => Some(id),
- _ => None,
- }
- }
-
- pub fn as_adt(self) -> Option<AdtId> {
- match self {
- LangItemTarget::Union(it) => Some(it.into()),
- LangItemTarget::EnumId(it) => Some(it.into()),
- LangItemTarget::Struct(it) => Some(it.into()),
- _ => None,
- }
- }
-}
+impl_from!(
+ EnumId, FunctionId, ImplId, StaticId, StructId, UnionId, TypeAliasId, TraitId, EnumVariantId for LangItemTarget
+);
/// Salsa query. This will look for lang items in a specific crate.
#[salsa_macros::tracked(returns(ref))]
-pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangItems>> {
+pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> LangItems {
let _p = tracing::info_span!("crate_lang_items_query").entered();
let mut lang_items = LangItems::default();
@@ -105,15 +40,11 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
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);
+ lang_items.collect_lang_item(db, impl_def);
for &(_, assoc) in impl_def.impl_items(db).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::FunctionId(f) => lang_items.collect_lang_item(db, f),
+ AssocItemId::TypeAliasId(t) => lang_items.collect_lang_item(db, t),
AssocItemId::ConstId(_) => (),
}
}
@@ -122,62 +53,55 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
for def in module_data.scope.declarations() {
match def {
ModuleDefId::TraitId(trait_) => {
- lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
+ lang_items.collect_lang_item(db, trait_);
TraitItems::query(db, 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);
}
AssocItemId::TypeAliasId(alias) => {
- lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
+ lang_items.collect_lang_item(db, alias)
}
AssocItemId::ConstId(_) => {}
}
});
}
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
- lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
+ lang_items.collect_lang_item(db, e);
e.enum_variants(db).variants.iter().for_each(|&(id, _, _)| {
- lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
+ lang_items.collect_lang_item(db, id);
});
}
ModuleDefId::AdtId(AdtId::StructId(s)) => {
- lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
+ lang_items.collect_lang_item(db, s);
}
ModuleDefId::AdtId(AdtId::UnionId(u)) => {
- lang_items.collect_lang_item(db, u, LangItemTarget::Union);
+ lang_items.collect_lang_item(db, u);
}
ModuleDefId::FunctionId(f) => {
- lang_items.collect_lang_item(db, f, LangItemTarget::Function);
+ lang_items.collect_lang_item(db, f);
}
ModuleDefId::StaticId(s) => {
- lang_items.collect_lang_item(db, s, LangItemTarget::Static);
+ lang_items.collect_lang_item(db, s);
}
ModuleDefId::TypeAliasId(t) => {
- lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
+ lang_items.collect_lang_item(db, t);
}
_ => {}
}
}
}
- if lang_items.items.is_empty() { None } else { Some(Box::new(lang_items)) }
+ lang_items
}
-/// Salsa query. Look for a lang item, starting from the specified crate and recursively
+/// Salsa query. Look for a lang items, starting from the specified crate and recursively
/// traversing its dependencies.
-#[salsa_macros::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);
- }
+#[salsa_macros::tracked(returns(ref))]
+pub fn lang_items(db: &dyn DefDatabase, start_crate: Crate) -> LangItems {
+ let _p = tracing::info_span!("lang_items_query").entered();
+
+ let mut result = crate_lang_items(db, start_crate).clone();
// Our `CrateGraph` eagerly inserts sysroot dependencies like `core` or `std` into dependencies
// even if the target crate has `#![no_std]`, `#![no_core]` or shadowed sysroot dependencies
@@ -186,42 +110,29 @@ pub fn lang_item(
// while nameres.
//
// See https://github.com/rust-lang/rust-analyzer/pull/20475 for details.
- crate_local_def_map(db, start_crate).local(db).extern_prelude().find_map(|(_, (krate, _))| {
+ for (_, (krate, _)) in crate_local_def_map(db, start_crate).local(db).extern_prelude() {
// Some crates declares themselves as extern crate like `extern crate self as core`.
// Ignore these to prevent cycles.
- if krate.krate == start_crate { None } else { lang_item(db, krate.krate, item) }
- })
-}
+ if krate.krate != start_crate {
+ result.merge_prefer_self(lang_items(db, krate.krate));
+ }
+ }
-#[derive(Default, Debug, Clone, PartialEq, Eq)]
-pub struct LangItems {
- items: FxHashMap<LangItem, LangItemTarget>,
+ result
}
impl LangItems {
- pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
- self.items.get(&item).copied()
- }
-
- fn collect_lang_item<T>(
- &mut self,
- db: &dyn DefDatabase,
- item: T,
- constructor: fn(T) -> LangItemTarget,
- ) where
- T: Into<AttrDefId> + Copy,
+ fn collect_lang_item<T>(&mut self, db: &dyn DefDatabase, item: T)
+ where
+ T: Into<AttrDefId> + Into<LangItemTarget> + Copy,
{
let _p = tracing::info_span!("collect_lang_item").entered();
- if let Some(lang_item) = lang_attr(db, item.into()) {
- self.items.entry(lang_item).or_insert_with(|| constructor(item));
+ if let Some(lang_item) = db.attrs(item.into()).lang_item() {
+ self.assign_lang_item(lang_item, item.into());
}
}
}
-pub(crate) fn lang_attr(db: &dyn DefDatabase, item: AttrDefId) -> Option<LangItem> {
- db.attrs(item).lang_item()
-}
-
#[salsa::tracked(returns(as_deref))]
pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option<Box<[TraitId]>> {
let mut traits = Vec::new();
@@ -249,173 +160,151 @@ pub enum GenericRequirement {
macro_rules! language_item_table {
(
- $( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
+ $( $(#[$attr:meta])* $lang_item:ident, $module:ident :: $name:ident, $method:ident, $target:ident, $generics:expr; )*
) => {
-
- /// A representation of all the valid language items in Rust.
- #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
- pub enum LangItem {
+ #[allow(non_snake_case)] // FIXME: Should we remove this?
+ #[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
+ pub struct LangItems {
$(
- #[doc = concat!("The `", stringify!($name), "` lang item.")]
$(#[$attr])*
- $variant,
+ pub $lang_item: Option<$target>,
)*
}
- impl LangItem {
- pub fn name(self) -> &'static str {
- match self {
- $( LangItem::$variant => stringify!($name), )*
- }
+ impl LangItems {
+ /// Merges `self` with `other`, with preference to `self` items.
+ fn merge_prefer_self(&mut self, other: &Self) {
+ $( self.$lang_item = self.$lang_item.or(other.$lang_item); )*
}
- /// Opposite of [`LangItem::name`]
- pub fn from_symbol(sym: &Symbol) -> Option<Self> {
- match sym {
- $(sym if *sym == $module::$name => Some(LangItem::$variant), )*
- _ => None,
+ fn assign_lang_item(&mut self, name: &Symbol, target: LangItemTarget) {
+ match name {
+ $(
+ _ if *name == $module::$name => {
+ if let LangItemTarget::$target(target) = target {
+ self.$lang_item = Some(target);
+ }
+ }
+ )*
+ _ => {}
}
}
}
- }
-}
-
-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_adt(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<AdtId> {
- lang_item(db, start_crate, self).and_then(|t| t.as_adt())
- }
-
- 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 = lang_item(db, start_crate, *self)?;
- Some(Path::LangItem(t, None))
- }
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+ pub enum LangItemEnum {
+ $(
+ $(#[$attr])*
+ $lang_item,
+ )*
+ }
- pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option<Path> {
- let t = lang_item(db, start_crate, *self)?;
- Some(Path::LangItem(t, Some(seg)))
+ impl LangItemEnum {
+ #[inline]
+ pub fn from_lang_items(self, lang_items: &LangItems) -> Option<LangItemTarget> {
+ match self {
+ $( LangItemEnum::$lang_item => lang_items.$lang_item.map(Into::into), )*
+ }
+ }
+ }
}
}
language_item_table! {
// Variant name, Name, Getter method name, Target Generic requirements;
- Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
- MetaSized, sym::meta_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
- PointeeSized, sym::pointee_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
- Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
+ Sized, sym::sized, sized_trait, TraitId, GenericRequirement::Exact(0);
+ MetaSized, sym::meta_sized, sized_trait, TraitId, GenericRequirement::Exact(0);
+ PointeeSized, sym::pointee_sized, sized_trait, TraitId, GenericRequirement::Exact(0);
+ Unsize, sym::unsize, unsize_trait, TraitId, GenericRequirement::Minimum(1);
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
- StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
+ StructuralPeq, sym::structural_peq, structural_peq_trait, TraitId, GenericRequirement::None;
/// Trait injected by `#[derive(Eq)]`, (i.e. "Total EQ"; no, I will not apologize).
- StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait, GenericRequirement::None;
- Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
- Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
- Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
- DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
+ StructuralTeq, sym::structural_teq, structural_teq_trait, TraitId, GenericRequirement::None;
+ Copy, sym::copy, copy_trait, TraitId, GenericRequirement::Exact(0);
+ Clone, sym::clone, clone_trait, TraitId, GenericRequirement::None;
+ Sync, sym::sync, sync_trait, TraitId, GenericRequirement::Exact(0);
+ DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, TraitId, GenericRequirement::None;
/// The associated item of the [`DiscriminantKind`] trait.
- Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy, GenericRequirement::None;
+ Discriminant, sym::discriminant_type, discriminant_type, TypeAliasId, GenericRequirement::None;
- PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait, GenericRequirement::None;
- Metadata, sym::metadata_type, metadata_type, Target::AssocTy, GenericRequirement::None;
- DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None;
+ PointeeTrait, sym::pointee_trait, pointee_trait, TraitId, GenericRequirement::None;
+ Metadata, sym::metadata_type, metadata_type, TypeAliasId, GenericRequirement::None;
+ DynMetadata, sym::dyn_metadata, dyn_metadata, StructId, GenericRequirement::None;
- Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
+ Freeze, sym::freeze, freeze_trait, TraitId, GenericRequirement::Exact(0);
- FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, Target::Trait, GenericRequirement::Exact(0);
- FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+ FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, TraitId, GenericRequirement::Exact(0);
+ FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, FunctionId, GenericRequirement::None;
- Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None;
- Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None;
+ Drop, sym::drop, drop_trait, TraitId, GenericRequirement::None;
+ Destruct, sym::destruct, destruct_trait, TraitId, GenericRequirement::None;
- CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
- DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
+ CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, TraitId, GenericRequirement::Minimum(1);
+ DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, TraitId, GenericRequirement::Minimum(1);
// language items relating to transmutability
- TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0);
- TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3);
-
- 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;
- UnsafePinned, sym::unsafe_pinned, unsafe_pinned_type, Target::Struct, GenericRequirement::None;
- VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
-
- Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0);
- DerefMut, sym::deref_mut, deref_mut_trait, Target::Trait, GenericRequirement::Exact(0);
- DerefTarget, sym::deref_target, deref_target, Target::AssocTy, GenericRequirement::None;
- Receiver, sym::receiver, receiver_trait, Target::Trait, GenericRequirement::None;
- ReceiverTarget, sym::receiver_target, receiver_target, Target::AssocTy, GenericRequirement::None;
-
- Fn, sym::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);
- AsyncFn, sym::async_fn, async_fn_trait, Target::Trait, GenericRequirement::Exact(1);
- AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, Target::Trait, GenericRequirement::Exact(1);
- AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, Target::Trait, GenericRequirement::Exact(1);
-
- CallRefFuture, sym::call_ref_future, call_ref_future_ty, Target::AssocTy, GenericRequirement::None;
- CallOnceFuture, sym::call_once_future, call_once_future_ty, Target::AssocTy, GenericRequirement::None;
- AsyncFnOnceOutput, sym::async_fn_once_output, async_fn_once_output_ty, Target::AssocTy, GenericRequirement::None;
-
- FnOnceOutput, sym::fn_once_output, fn_once_output, Target::AssocTy, GenericRequirement::None;
-
- Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
- CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
- Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1);
- CoroutineReturn, sym::coroutine_return, coroutine_return_ty, Target::AssocTy, GenericRequirement::None;
- CoroutineYield, sym::coroutine_yield, coroutine_yield_ty, Target::AssocTy, GenericRequirement::None;
- Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
- Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
-
- PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1);
- PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1);
- CVoid, sym::c_void, c_void, Target::Enum, GenericRequirement::None;
+ TransmuteOpts, sym::transmute_opts, transmute_opts, StructId, GenericRequirement::Exact(0);
+ TransmuteTrait, sym::transmute_trait, transmute_trait, TraitId, GenericRequirement::Exact(3);
+
+ Add, sym::add, add_trait, TraitId, GenericRequirement::Exact(1);
+ Sub, sym::sub, sub_trait, TraitId, GenericRequirement::Exact(1);
+ Mul, sym::mul, mul_trait, TraitId, GenericRequirement::Exact(1);
+ Div, sym::div, div_trait, TraitId, GenericRequirement::Exact(1);
+ Rem, sym::rem, rem_trait, TraitId, GenericRequirement::Exact(1);
+ Neg, sym::neg, neg_trait, TraitId, GenericRequirement::Exact(0);
+ Not, sym::not, not_trait, TraitId, GenericRequirement::Exact(0);
+ BitXor, sym::bitxor, bitxor_trait, TraitId, GenericRequirement::Exact(1);
+ BitAnd, sym::bitand, bitand_trait, TraitId, GenericRequirement::Exact(1);
+ BitOr, sym::bitor, bitor_trait, TraitId, GenericRequirement::Exact(1);
+ Shl, sym::shl, shl_trait, TraitId, GenericRequirement::Exact(1);
+ Shr, sym::shr, shr_trait, TraitId, GenericRequirement::Exact(1);
+ AddAssign, sym::add_assign, add_assign_trait, TraitId, GenericRequirement::Exact(1);
+ SubAssign, sym::sub_assign, sub_assign_trait, TraitId, GenericRequirement::Exact(1);
+ MulAssign, sym::mul_assign, mul_assign_trait, TraitId, GenericRequirement::Exact(1);
+ DivAssign, sym::div_assign, div_assign_trait, TraitId, GenericRequirement::Exact(1);
+ RemAssign, sym::rem_assign, rem_assign_trait, TraitId, GenericRequirement::Exact(1);
+ BitXorAssign, sym::bitxor_assign, bitxor_assign_trait, TraitId, GenericRequirement::Exact(1);
+ BitAndAssign, sym::bitand_assign, bitand_assign_trait, TraitId, GenericRequirement::Exact(1);
+ BitOrAssign, sym::bitor_assign, bitor_assign_trait, TraitId, GenericRequirement::Exact(1);
+ ShlAssign, sym::shl_assign, shl_assign_trait, TraitId, GenericRequirement::Exact(1);
+ ShrAssign, sym::shr_assign, shr_assign_trait, TraitId, GenericRequirement::Exact(1);
+ Index, sym::index, index_trait, TraitId, GenericRequirement::Exact(1);
+ IndexMut, sym::index_mut, index_mut_trait, TraitId, GenericRequirement::Exact(1);
+
+ UnsafeCell, sym::unsafe_cell, unsafe_cell_type, StructId, GenericRequirement::None;
+ UnsafePinned, sym::unsafe_pinned, unsafe_pinned_type, StructId, GenericRequirement::None;
+ VaList, sym::va_list, va_list, StructId, GenericRequirement::None;
+
+ Deref, sym::deref, deref_trait, TraitId, GenericRequirement::Exact(0);
+ DerefMut, sym::deref_mut, deref_mut_trait, TraitId, GenericRequirement::Exact(0);
+ DerefTarget, sym::deref_target, deref_target, TypeAliasId, GenericRequirement::None;
+ Receiver, sym::receiver, receiver_trait, TraitId, GenericRequirement::None;
+ ReceiverTarget, sym::receiver_target, receiver_target, TypeAliasId, GenericRequirement::None;
+
+ Fn, sym::fn_, fn_trait, TraitId, GenericRequirement::Exact(1);
+ FnMut, sym::fn_mut, fn_mut_trait, TraitId, GenericRequirement::Exact(1);
+ FnOnce, sym::fn_once, fn_once_trait, TraitId, GenericRequirement::Exact(1);
+ AsyncFn, sym::async_fn, async_fn_trait, TraitId, GenericRequirement::Exact(1);
+ AsyncFnMut, sym::async_fn_mut, async_fn_mut_trait, TraitId, GenericRequirement::Exact(1);
+ AsyncFnOnce, sym::async_fn_once, async_fn_once_trait, TraitId, GenericRequirement::Exact(1);
+
+ CallRefFuture, sym::call_ref_future, call_ref_future_ty, TypeAliasId, GenericRequirement::None;
+ CallOnceFuture, sym::call_once_future, call_once_future_ty, TypeAliasId, GenericRequirement::None;
+ AsyncFnOnceOutput, sym::async_fn_once_output, async_fn_once_output_ty, TypeAliasId, GenericRequirement::None;
+
+ FnOnceOutput, sym::fn_once_output, fn_once_output, TypeAliasId, GenericRequirement::None;
+
+ Future, sym::future_trait, future_trait, TraitId, GenericRequirement::Exact(0);
+ CoroutineState, sym::coroutine_state, coroutine_state, EnumId, GenericRequirement::None;
+ Coroutine, sym::coroutine, coroutine_trait, TraitId, GenericRequirement::Minimum(1);
+ CoroutineReturn, sym::coroutine_return, coroutine_return_ty, TypeAliasId, GenericRequirement::None;
+ CoroutineYield, sym::coroutine_yield, coroutine_yield_ty, TypeAliasId, GenericRequirement::None;
+ Unpin, sym::unpin, unpin_trait, TraitId, GenericRequirement::None;
+ Pin, sym::pin, pin_type, StructId, GenericRequirement::None;
+
+ PartialEq, sym::eq, eq_trait, TraitId, GenericRequirement::Exact(1);
+ PartialOrd, sym::partial_ord, partial_ord_trait, TraitId, GenericRequirement::Exact(1);
+ CVoid, sym::c_void, c_void, EnumId, GenericRequirement::None;
// 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.
@@ -424,107 +313,107 @@ language_item_table! {
// in the sense that a crate is not required to have it defined to use it, but a final product
// is required to define it somewhere. Additionally, there are restrictions on crates that use
// a weak lang item, but do not have it defined.
- Panic, sym::panic, panic_fn, Target::Fn, GenericRequirement::Exact(0);
- PanicNounwind, sym::panic_nounwind, panic_nounwind, Target::Fn, GenericRequirement::Exact(0);
- PanicFmt, sym::panic_fmt, panic_fmt, Target::Fn, GenericRequirement::None;
- PanicDisplay, sym::panic_display, panic_display, Target::Fn, GenericRequirement::None;
- ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, Target::Fn, GenericRequirement::None;
- PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, Target::Fn, GenericRequirement::Exact(0);
- PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, Target::Fn, GenericRequirement::Exact(0);
- PanicInfo, sym::panic_info, panic_info, Target::Struct, GenericRequirement::None;
- PanicLocation, sym::panic_location, panic_location, Target::Struct, GenericRequirement::None;
- PanicImpl, sym::panic_impl, panic_impl, Target::Fn, GenericRequirement::None;
- PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, Target::Fn, GenericRequirement::Exact(0);
- PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, Target::Fn, GenericRequirement::None;
+ Panic, sym::panic, panic_fn, FunctionId, GenericRequirement::Exact(0);
+ PanicNounwind, sym::panic_nounwind, panic_nounwind, FunctionId, GenericRequirement::Exact(0);
+ PanicFmt, sym::panic_fmt, panic_fmt, FunctionId, GenericRequirement::None;
+ PanicDisplay, sym::panic_display, panic_display, FunctionId, GenericRequirement::None;
+ ConstPanicFmt, sym::const_panic_fmt, const_panic_fmt, FunctionId, GenericRequirement::None;
+ PanicBoundsCheck, sym::panic_bounds_check, panic_bounds_check_fn, FunctionId, GenericRequirement::Exact(0);
+ PanicMisalignedPointerDereference, sym::panic_misaligned_pointer_dereference, panic_misaligned_pointer_dereference_fn, FunctionId, GenericRequirement::Exact(0);
+ PanicInfo, sym::panic_info, panic_info, StructId, GenericRequirement::None;
+ PanicLocation, sym::panic_location, panic_location, StructId, GenericRequirement::None;
+ PanicImpl, sym::panic_impl, panic_impl, FunctionId, GenericRequirement::None;
+ PanicCannotUnwind, sym::panic_cannot_unwind, panic_cannot_unwind, FunctionId, GenericRequirement::Exact(0);
+ PanicNullPointerDereference, sym::panic_null_pointer_dereference, panic_null_pointer_dereference, FunctionId, GenericRequirement::None;
/// libstd panic entry point. Necessary for const eval to be able to catch it
- BeginPanic, sym::begin_panic, begin_panic_fn, Target::Fn, GenericRequirement::None;
+ BeginPanic, sym::begin_panic, begin_panic_fn, FunctionId, GenericRequirement::None;
// Lang items needed for `format_args!()`.
- FormatAlignment, sym::format_alignment, format_alignment, Target::Enum, GenericRequirement::None;
- FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None;
- FormatArguments, sym::format_arguments, format_arguments, Target::Struct, GenericRequirement::None;
- FormatCount, sym::format_count, format_count, Target::Enum, GenericRequirement::None;
- FormatPlaceholder, sym::format_placeholder, format_placeholder, Target::Struct, GenericRequirement::None;
- FormatUnsafeArg, sym::format_unsafe_arg, format_unsafe_arg, Target::Struct, GenericRequirement::None;
+ FormatAlignment, sym::format_alignment, format_alignment, EnumId, GenericRequirement::None;
+ FormatArgument, sym::format_argument, format_argument, StructId, GenericRequirement::None;
+ FormatArguments, sym::format_arguments, format_arguments, StructId, GenericRequirement::None;
+ FormatCount, sym::format_count, format_count, EnumId, GenericRequirement::None;
+ FormatPlaceholder, sym::format_placeholder, format_placeholder, StructId, GenericRequirement::None;
+ FormatUnsafeArg, sym::format_unsafe_arg, format_unsafe_arg, StructId, GenericRequirement::None;
- ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
- BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1);
- DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
- AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;
+ ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, FunctionId, GenericRequirement::None;
+ BoxFree, sym::box_free, box_free_fn, FunctionId, GenericRequirement::Minimum(1);
+ DropInPlace, sym::drop_in_place, drop_in_place_fn, FunctionId, GenericRequirement::Minimum(1);
+ AllocLayout, sym::alloc_layout, alloc_layout, StructId, GenericRequirement::None;
- Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1);
+ Start, sym::start, start_fn, FunctionId, GenericRequirement::Exact(1);
- EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None;
- EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None;
+ EhPersonality, sym::eh_personality, eh_personality, FunctionId, GenericRequirement::None;
+ EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, StaticId, GenericRequirement::None;
- OwnedBox, sym::owned_box, owned_box, Target::Struct, GenericRequirement::Minimum(1);
+ OwnedBox, sym::owned_box, owned_box, StructId, GenericRequirement::Minimum(1);
- PhantomData, sym::phantom_data, phantom_data, Target::Struct, GenericRequirement::Exact(1);
+ PhantomData, sym::phantom_data, phantom_data, StructId, GenericRequirement::Exact(1);
- ManuallyDrop, sym::manually_drop, manually_drop, Target::Struct, GenericRequirement::None;
+ ManuallyDrop, sym::manually_drop, manually_drop, StructId, GenericRequirement::None;
- MaybeUninit, sym::maybe_uninit, maybe_uninit, Target::Union, GenericRequirement::None;
+ MaybeUninit, sym::maybe_uninit, maybe_uninit, UnionId, GenericRequirement::None;
/// Align offset for stride != 1; must not panic.
- AlignOffset, sym::align_offset, align_offset_fn, Target::Fn, GenericRequirement::None;
+ AlignOffset, sym::align_offset, align_offset_fn, FunctionId, GenericRequirement::None;
- Termination, sym::termination, termination, Target::Trait, GenericRequirement::None;
+ Termination, sym::termination, termination, TraitId, GenericRequirement::None;
- Try, sym::Try, try_trait, Target::Trait, GenericRequirement::None;
+ Try, sym::Try, try_trait, TraitId, GenericRequirement::None;
- Tuple, sym::tuple_trait, tuple_trait, Target::Trait, GenericRequirement::Exact(0);
+ Tuple, sym::tuple_trait, tuple_trait, TraitId, GenericRequirement::Exact(0);
- SliceLen, sym::slice_len_fn, slice_len_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
+ SliceLen, sym::slice_len_fn, slice_len_fn, FunctionId, GenericRequirement::None;
// Language items from AST lowering
- TryTraitFromResidual, sym::from_residual, from_residual_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
- TryTraitFromOutput, sym::from_output, from_output_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
- TryTraitBranch, sym::branch, branch_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
- TryTraitFromYeet, sym::from_yeet, from_yeet_fn, Target::Fn, GenericRequirement::None;
+ TryTraitFromResidual, sym::from_residual, from_residual_fn, FunctionId, GenericRequirement::None;
+ TryTraitFromOutput, sym::from_output, from_output_fn, FunctionId, GenericRequirement::None;
+ TryTraitBranch, sym::branch, branch_fn, FunctionId, GenericRequirement::None;
+ TryTraitFromYeet, sym::from_yeet, from_yeet_fn, FunctionId, GenericRequirement::None;
- PointerLike, sym::pointer_like, pointer_like, Target::Trait, GenericRequirement::Exact(0);
+ PointerLike, sym::pointer_like, pointer_like, TraitId, GenericRequirement::Exact(0);
- ConstParamTy, sym::const_param_ty, const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
+ ConstParamTy, sym::const_param_ty, const_param_ty_trait, TraitId, GenericRequirement::Exact(0);
- Poll, sym::Poll, poll, Target::Enum, GenericRequirement::None;
- PollReady, sym::Ready, poll_ready_variant, Target::Variant, GenericRequirement::None;
- PollPending, sym::Pending, poll_pending_variant, Target::Variant, GenericRequirement::None;
+ Poll, sym::Poll, poll, EnumId, GenericRequirement::None;
+ PollReady, sym::Ready, poll_ready_variant, EnumVariantId, GenericRequirement::None;
+ PollPending, sym::Pending, poll_pending_variant, EnumVariantId, GenericRequirement::None;
// FIXME(swatinem): the following lang items are used for async lowering and
// should become obsolete eventually.
- ResumeTy, sym::ResumeTy, resume_ty, Target::Struct, GenericRequirement::None;
- GetContext, sym::get_context, get_context_fn, Target::Fn, GenericRequirement::None;
+ ResumeTy, sym::ResumeTy, resume_ty, StructId, GenericRequirement::None;
+ GetContext, sym::get_context, get_context_fn, FunctionId, GenericRequirement::None;
- Context, sym::Context, context, Target::Struct, GenericRequirement::None;
- FuturePoll, sym::poll, future_poll_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
- FutureOutput, sym::future_output, future_output, Target::TypeAlias, GenericRequirement::None;
+ Context, sym::Context, context, StructId, GenericRequirement::None;
+ FuturePoll, sym::poll, future_poll_fn, FunctionId, GenericRequirement::None;
+ FutureOutput, sym::future_output, future_output, TypeAliasId, GenericRequirement::None;
- Option, sym::Option, option_type, Target::Enum, GenericRequirement::None;
- OptionSome, sym::Some, option_some_variant, Target::Variant, GenericRequirement::None;
- OptionNone, sym::None, option_none_variant, Target::Variant, GenericRequirement::None;
+ Option, sym::Option, option_type, EnumId, GenericRequirement::None;
+ OptionSome, sym::Some, option_some_variant, EnumVariantId, GenericRequirement::None;
+ OptionNone, sym::None, option_none_variant, EnumVariantId, GenericRequirement::None;
- ResultOk, sym::Ok, result_ok_variant, Target::Variant, GenericRequirement::None;
- ResultErr, sym::Err, result_err_variant, Target::Variant, GenericRequirement::None;
+ ResultOk, sym::Ok, result_ok_variant, EnumVariantId, GenericRequirement::None;
+ ResultErr, sym::Err, result_err_variant, EnumVariantId, GenericRequirement::None;
- ControlFlowContinue, sym::Continue, cf_continue_variant, Target::Variant, GenericRequirement::None;
- ControlFlowBreak, sym::Break, cf_break_variant, Target::Variant, GenericRequirement::None;
+ ControlFlowContinue, sym::Continue, cf_continue_variant, EnumVariantId, GenericRequirement::None;
+ ControlFlowBreak, sym::Break, cf_break_variant, EnumVariantId, GenericRequirement::None;
- IntoFutureIntoFuture, sym::into_future, into_future_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
- IntoIterIntoIter, sym::into_iter, into_iter_fn, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
- IteratorNext, sym::next, next_fn, Target::Method(MethodKind::Trait { body: false}), GenericRequirement::None;
- Iterator, sym::iterator, iterator, Target::Trait, GenericRequirement::None;
+ IntoFutureIntoFuture, sym::into_future, into_future_fn, FunctionId, GenericRequirement::None;
+ IntoIterIntoIter, sym::into_iter, into_iter_fn, FunctionId, GenericRequirement::None;
+ IteratorNext, sym::next, next_fn, FunctionId, GenericRequirement::None;
+ Iterator, sym::iterator, iterator, TraitId, GenericRequirement::None;
- PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, Target::Method(MethodKind::Inherent), GenericRequirement::None;
+ PinNewUnchecked, sym::new_unchecked, new_unchecked_fn, FunctionId, GenericRequirement::None;
- RangeFrom, sym::RangeFrom, range_from_struct, Target::Struct, GenericRequirement::None;
- RangeFull, sym::RangeFull, range_full_struct, Target::Struct, GenericRequirement::None;
- RangeInclusiveStruct, sym::RangeInclusive, range_inclusive_struct, Target::Struct, GenericRequirement::None;
- RangeInclusiveNew, sym::range_inclusive_new, range_inclusive_new_method, Target::Method(MethodKind::Inherent), GenericRequirement::None;
- Range, sym::Range, range_struct, Target::Struct, GenericRequirement::None;
- RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, Target::Struct, GenericRequirement::None;
- RangeTo, sym::RangeTo, range_to_struct, Target::Struct, GenericRequirement::None;
+ RangeFrom, sym::RangeFrom, range_from_struct, StructId, GenericRequirement::None;
+ RangeFull, sym::RangeFull, range_full_struct, StructId, GenericRequirement::None;
+ RangeInclusiveStruct, sym::RangeInclusive, range_inclusive_struct, StructId, GenericRequirement::None;
+ RangeInclusiveNew, sym::range_inclusive_new, range_inclusive_new_method, FunctionId, GenericRequirement::None;
+ Range, sym::Range, range_struct, StructId, GenericRequirement::None;
+ RangeToInclusive, sym::RangeToInclusive, range_to_inclusive_struct, StructId, GenericRequirement::None;
+ RangeTo, sym::RangeTo, range_to_struct, StructId, GenericRequirement::None;
- String, sym::String, string, Target::Struct, GenericRequirement::None;
- CStr, sym::CStr, c_str, Target::Struct, GenericRequirement::None;
- Ordering, sym::Ordering, ordering, Target::Enum, GenericRequirement::None;
+ String, sym::String, string, StructId, GenericRequirement::None;
+ CStr, sym::CStr, c_str, StructId, GenericRequirement::None;
+ Ordering, sym::Ordering, ordering, EnumId, GenericRequirement::None;
}
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index b5afbf387d..ccea043739 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -186,15 +186,15 @@ impl<'db> Resolver<'db> {
Path::Normal(it) => &it.mod_path,
Path::LangItem(l, seg) => {
let type_ns = match *l {
- LangItemTarget::Union(it) => TypeNs::AdtId(it.into()),
- LangItemTarget::TypeAlias(it) => TypeNs::TypeAliasId(it),
- LangItemTarget::Struct(it) => TypeNs::AdtId(it.into()),
- LangItemTarget::EnumVariant(it) => TypeNs::EnumVariantId(it),
+ LangItemTarget::UnionId(it) => TypeNs::AdtId(it.into()),
+ LangItemTarget::TypeAliasId(it) => TypeNs::TypeAliasId(it),
+ LangItemTarget::StructId(it) => TypeNs::AdtId(it.into()),
+ LangItemTarget::EnumVariantId(it) => TypeNs::EnumVariantId(it),
LangItemTarget::EnumId(it) => TypeNs::AdtId(it.into()),
- LangItemTarget::Trait(it) => TypeNs::TraitId(it),
- LangItemTarget::Function(_)
- | LangItemTarget::ImplDef(_)
- | LangItemTarget::Static(_) => return None,
+ LangItemTarget::TraitId(it) => TypeNs::TraitId(it),
+ LangItemTarget::FunctionId(_)
+ | LangItemTarget::ImplId(_)
+ | LangItemTarget::StaticId(_) => return None,
};
return Some((
type_ns,
@@ -334,14 +334,14 @@ impl<'db> Resolver<'db> {
return Some((
ResolveValueResult::ValueNs(
match *l {
- LangItemTarget::Function(it) => ValueNs::FunctionId(it),
- LangItemTarget::Static(it) => ValueNs::StaticId(it),
- LangItemTarget::Struct(it) => ValueNs::StructId(it),
- LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it),
- LangItemTarget::Union(_)
- | LangItemTarget::ImplDef(_)
- | LangItemTarget::TypeAlias(_)
- | LangItemTarget::Trait(_)
+ LangItemTarget::FunctionId(it) => ValueNs::FunctionId(it),
+ LangItemTarget::StaticId(it) => ValueNs::StaticId(it),
+ LangItemTarget::StructId(it) => ValueNs::StructId(it),
+ LangItemTarget::EnumVariantId(it) => ValueNs::EnumVariantId(it),
+ LangItemTarget::UnionId(_)
+ | LangItemTarget::ImplId(_)
+ | LangItemTarget::TypeAliasId(_)
+ | LangItemTarget::TraitId(_)
| LangItemTarget::EnumId(_) => return None,
},
None,
@@ -351,15 +351,15 @@ impl<'db> Resolver<'db> {
}
Path::LangItem(l, Some(_)) => {
let type_ns = match *l {
- LangItemTarget::Union(it) => TypeNs::AdtId(it.into()),
- LangItemTarget::TypeAlias(it) => TypeNs::TypeAliasId(it),
- LangItemTarget::Struct(it) => TypeNs::AdtId(it.into()),
- LangItemTarget::EnumVariant(it) => TypeNs::EnumVariantId(it),
+ LangItemTarget::UnionId(it) => TypeNs::AdtId(it.into()),
+ LangItemTarget::TypeAliasId(it) => TypeNs::TypeAliasId(it),
+ LangItemTarget::StructId(it) => TypeNs::AdtId(it.into()),
+ LangItemTarget::EnumVariantId(it) => TypeNs::EnumVariantId(it),
LangItemTarget::EnumId(it) => TypeNs::AdtId(it.into()),
- LangItemTarget::Trait(it) => TypeNs::TraitId(it),
- LangItemTarget::Function(_)
- | LangItemTarget::ImplDef(_)
- | LangItemTarget::Static(_) => return None,
+ LangItemTarget::TraitId(it) => TypeNs::TraitId(it),
+ LangItemTarget::FunctionId(_)
+ | LangItemTarget::ImplId(_)
+ | LangItemTarget::StaticId(_) => return None,
};
// Remaining segments start from 0 because lang paths have no segments other than the remaining.
return Some((
diff --git a/crates/hir-def/src/signatures.rs b/crates/hir-def/src/signatures.rs
index ebbf87cad6..405bb44559 100644
--- a/crates/hir-def/src/signatures.rs
+++ b/crates/hir-def/src/signatures.rs
@@ -31,7 +31,6 @@ use crate::{
},
hir::{ExprId, PatId, generics::GenericParams},
item_tree::{FieldsShape, RawVisibility, visibility_from_ast},
- lang_item::LangItem,
src::HasSource,
type_ref::{TraitRef, TypeBound, TypeRefId},
};
@@ -86,11 +85,11 @@ impl StructSignature {
}
if let Some(lang) = attrs.lang_item() {
match lang {
- LangItem::PhantomData => flags |= StructFlags::IS_PHANTOM_DATA,
- LangItem::OwnedBox => flags |= StructFlags::IS_BOX,
- LangItem::ManuallyDrop => flags |= StructFlags::IS_MANUALLY_DROP,
- LangItem::UnsafeCell => flags |= StructFlags::IS_UNSAFE_CELL,
- LangItem::UnsafePinned => flags |= StructFlags::IS_UNSAFE_PINNED,
+ _ if *lang == sym::phantom_data => flags |= StructFlags::IS_PHANTOM_DATA,
+ _ if *lang == sym::owned_box => flags |= StructFlags::IS_BOX,
+ _ if *lang == sym::manually_drop => flags |= StructFlags::IS_MANUALLY_DROP,
+ _ if *lang == sym::unsafe_cell => flags |= StructFlags::IS_UNSAFE_CELL,
+ _ if *lang == sym::unsafe_pinned => flags |= StructFlags::IS_UNSAFE_PINNED,
_ => (),
}
}
diff --git a/crates/hir-ty/src/autoderef.rs b/crates/hir-ty/src/autoderef.rs
index 47d06be893..4efe64377b 100644
--- a/crates/hir-ty/src/autoderef.rs
+++ b/crates/hir-ty/src/autoderef.rs
@@ -5,7 +5,7 @@
use std::fmt;
-use hir_def::{TraitId, TypeAliasId, lang_item::LangItem};
+use hir_def::{TraitId, TypeAliasId};
use rustc_type_ir::inherent::{IntoKind, Ty as _};
use tracing::debug;
use triomphe::Arc;
@@ -301,36 +301,28 @@ where
self.infcx().interner
}
- #[inline]
- fn db(&self) -> &'db dyn HirDatabase {
- self.interner().db
- }
-
fn autoderef_traits(&mut self) -> Option<AutoderefTraits> {
+ let lang_items = self.interner().lang_items();
match &mut self.traits {
Some(it) => Some(*it),
None => {
let traits = if self.use_receiver_trait {
(|| {
Some(AutoderefTraits {
- trait_: LangItem::Receiver
- .resolve_trait(self.db(), self.env().krate)?,
- trait_target: LangItem::ReceiverTarget
- .resolve_type_alias(self.db(), self.env().krate)?,
+ trait_: lang_items.Receiver?,
+ trait_target: lang_items.ReceiverTarget?,
})
})()
.or_else(|| {
Some(AutoderefTraits {
- trait_: LangItem::Deref.resolve_trait(self.db(), self.env().krate)?,
- trait_target: LangItem::DerefTarget
- .resolve_type_alias(self.db(), self.env().krate)?,
+ trait_: lang_items.Deref?,
+ trait_target: lang_items.DerefTarget?,
})
})?
} else {
AutoderefTraits {
- trait_: LangItem::Deref.resolve_trait(self.db(), self.env().krate)?,
- trait_target: LangItem::DerefTarget
- .resolve_type_alias(self.db(), self.env().krate)?,
+ trait_: lang_items.Deref?,
+ trait_target: lang_items.DerefTarget?,
}
};
Some(*self.traits.insert(traits))
diff --git a/crates/hir-ty/src/diagnostics/expr.rs b/crates/hir-ty/src/diagnostics/expr.rs
index 565b91df52..b84b70c197 100644
--- a/crates/hir-ty/src/diagnostics/expr.rs
+++ b/crates/hir-ty/src/diagnostics/expr.rs
@@ -8,7 +8,7 @@ use base_db::Crate;
use either::Either;
use hir_def::{
AdtId, AssocItemId, DefWithBodyId, HasModule, ItemContainerId, Lookup,
- lang_item::LangItem,
+ lang_item::LangItems,
resolver::{HasResolver, ValueNs},
};
use intern::sym;
@@ -187,7 +187,7 @@ impl<'db> ExprValidator<'db> {
};
let checker = filter_map_next_checker.get_or_insert_with(|| {
- FilterMapNextChecker::new(&self.owner.resolver(self.db()), self.db())
+ FilterMapNextChecker::new(self.infcx.interner.lang_items(), self.db())
});
if checker.check(call_id, receiver, &callee).is_some() {
@@ -497,11 +497,9 @@ struct FilterMapNextChecker<'db> {
}
impl<'db> FilterMapNextChecker<'db> {
- fn new(resolver: &hir_def::resolver::Resolver<'db>, db: &'db dyn HirDatabase) -> Self {
+ fn new(lang_items: &'db LangItems, db: &'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 LangItem::IteratorNext
- .resolve_function(db, resolver.krate())
- {
+ let (next_function_id, filter_map_function_id) = match lang_items.IteratorNext {
Some(next_function_id) => (
Some(next_function_id),
match next_function_id.lookup(db).container {
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 4b4ada45ae..2c6d7c68d1 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -17,7 +17,7 @@ use hir_def::{
hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
item_scope::ItemInNs,
item_tree::FieldsShape,
- lang_item::LangItem,
+ lang_item::LangItems,
nameres::DefMap,
signatures::VariantFields,
type_ref::{
@@ -61,7 +61,7 @@ use crate::{
infer::{DbInternerInferExt, traits::ObligationCause},
},
primitive,
- utils::{self, detect_variant_from_bytes},
+ utils::{detect_variant_from_bytes, fn_traits},
};
pub trait HirWrite: fmt::Write {
@@ -391,6 +391,11 @@ impl<'db> HirFormatter<'_, 'db> {
self.display_target.edition
}
+ #[inline]
+ pub fn lang_items(&self) -> &'db LangItems {
+ self.interner.lang_items()
+ }
+
pub fn write_joined<T: HirDisplay<'db>>(
&mut self,
iter: impl IntoIterator<Item = T>,
@@ -1101,7 +1106,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
bounds.iter().any(|bound| match bound.skip_binder() {
ExistentialPredicate::Trait(trait_ref) => {
let trait_ = trait_ref.def_id.0;
- fn_traits(db, trait_).any(|it| it == trait_)
+ fn_traits(f.lang_items()).any(|it| it == trait_)
}
_ => false,
});
@@ -1145,7 +1150,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
let contains_impl_fn = bounds().any(|bound| {
if let ClauseKind::Trait(trait_ref) = bound.kind().skip_binder() {
let trait_ = trait_ref.def_id().0;
- fn_traits(db, trait_).any(|it| it == trait_)
+ fn_traits(f.lang_items()).any(|it| it == trait_)
} else {
false
}
@@ -1587,8 +1592,7 @@ impl<'db> HirDisplay<'db> for Ty<'db> {
..
}
| hir_def::hir::Expr::Async { .. } => {
- let future_trait =
- LangItem::Future.resolve_trait(db, owner.module(db).krate());
+ let future_trait = f.lang_items().Future;
let output = future_trait.and_then(|t| {
t.trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Output))
@@ -1798,11 +1802,6 @@ impl<'db> HirDisplay<'db> for Term<'db> {
}
}
-fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = TraitId> + '_ {
- let krate = trait_.lookup(db).container.krate();
- utils::fn_traits(db, krate)
-}
-
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum SizedByDefault {
NotSized,
@@ -1814,7 +1813,7 @@ impl SizedByDefault {
match self {
Self::NotSized => false,
Self::Sized { anchor } => {
- let sized_trait = LangItem::Sized.resolve_trait(db, anchor);
+ let sized_trait = hir_def::lang_item::lang_items(db, anchor).Sized;
Some(trait_) == sized_trait
}
}
@@ -1867,7 +1866,7 @@ fn write_bounds_like_dyn_trait<'db>(
}
}
if !is_fn_trait {
- is_fn_trait = fn_traits(f.db, trait_).any(|it| it == trait_);
+ is_fn_trait = fn_traits(f.lang_items()).any(|it| it == trait_);
}
if !is_fn_trait && angle_open {
write!(f, ">")?;
@@ -1965,7 +1964,7 @@ fn write_bounds_like_dyn_trait<'db>(
write!(f, ">")?;
}
if let SizedByDefault::Sized { anchor } = default_sized {
- let sized_trait = LangItem::Sized.resolve_trait(f.db, anchor);
+ let sized_trait = hir_def::lang_item::lang_items(f.db, anchor).Sized;
if !is_sized {
if !first {
write!(f, " + ")?;
diff --git a/crates/hir-ty/src/drop.rs b/crates/hir-ty/src/drop.rs
index aebb6def93..124e7b279f 100644
--- a/crates/hir-ty/src/drop.rs
+++ b/crates/hir-ty/src/drop.rs
@@ -1,6 +1,6 @@
//! Utilities for computing drop info about types.
-use hir_def::{AdtId, lang_item::LangItem, signatures::StructFlags};
+use hir_def::{AdtId, signatures::StructFlags};
use rustc_hash::FxHashSet;
use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike};
use stdx::never;
@@ -8,22 +8,22 @@ use triomphe::Arc;
use crate::{
TraitEnvironment, consteval,
- db::HirDatabase,
method_resolution::TraitImpls,
next_solver::{
- SimplifiedType, Ty, TyKind,
+ DbInterner, SimplifiedType, Ty, TyKind,
infer::{InferCtxt, traits::ObligationCause},
obligation_ctxt::ObligationCtxt,
},
};
-fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool {
+fn has_destructor(interner: DbInterner<'_>, adt: AdtId) -> bool {
+ let db = interner.db;
let module = match adt {
AdtId::EnumId(id) => db.lookup_intern_enum(id).container,
AdtId::StructId(id) => db.lookup_intern_struct(id).container,
AdtId::UnionId(id) => db.lookup_intern_union(id).container,
};
- let Some(drop_trait) = LangItem::Drop.resolve_trait(db, module.krate()) else {
+ let Some(drop_trait) = interner.lang_items().Drop else {
return false;
};
let impls = match module.containing_block() {
@@ -73,7 +73,7 @@ fn has_drop_glue_impl<'db>(
match ty.kind() {
TyKind::Adt(adt_def, subst) => {
let adt_id = adt_def.def_id().0;
- if has_destructor(db, adt_id) {
+ if has_destructor(infcx.interner, adt_id) {
return DropGlue::HasDropGlue;
}
match adt_id {
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs
index d6de9ca7f4..a658302b09 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/crates/hir-ty/src/dyn_compatibility.rs
@@ -5,7 +5,7 @@ use std::ops::ControlFlow;
use hir_def::{
AssocItemId, ConstId, CrateRootModuleId, FunctionId, GenericDefId, HasModule, TraitId,
TypeAliasId, TypeOrConstParamId, TypeParamId, hir::generics::LocalTypeOrConstParamId,
- lang_item::LangItem, signatures::TraitFlags,
+ signatures::TraitFlags,
};
use rustc_hash::FxHashSet;
use rustc_type_ir::{
@@ -131,11 +131,11 @@ pub fn dyn_compatibility_of_trait_query(
pub fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool {
let krate = def.module(db).krate();
- let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else {
+ let interner = DbInterner::new_with(db, krate, None);
+ let Some(sized) = interner.lang_items().Sized else {
return false;
};
- let interner = DbInterner::new_no_crate(db);
let predicates = GenericPredicates::query_explicit(db, def);
// FIXME: We should use `explicit_predicates_of` here, which hasn't been implemented to
// rust-analyzer yet
@@ -420,16 +420,13 @@ fn receiver_is_dispatchable<'db>(
return false;
};
- let krate = func.module(db).krate();
- let traits = (
- LangItem::Unsize.resolve_trait(db, krate),
- LangItem::DispatchFromDyn.resolve_trait(db, krate),
- );
+ let lang_items = interner.lang_items();
+ let traits = (lang_items.Unsize, lang_items.DispatchFromDyn);
let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else {
return false;
};
- let meta_sized_did = LangItem::MetaSized.resolve_trait(db, krate);
+ let meta_sized_did = lang_items.MetaSized;
let Some(meta_sized_did) = meta_sized_did else {
return false;
};
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 17de94b7df..b671f84b7c 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -37,7 +37,7 @@ use hir_def::{
ItemContainerId, LocalFieldId, Lookup, TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId,
expr_store::{Body, ExpressionStore, HygieneId, path::Path},
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
- lang_item::{LangItem, LangItemTarget, lang_item},
+ lang_item::LangItems,
layout::Integer,
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
signatures::{ConstSignature, StaticSignature},
@@ -821,6 +821,7 @@ pub(crate) struct InferenceContext<'body, 'db> {
pub(crate) edition: Edition,
pub(crate) generic_def: GenericDefId,
pub(crate) table: unify::InferenceTable<'db>,
+ pub(crate) lang_items: &'db LangItems,
/// The traits in scope, disregarding block modules. This is used for caching purposes.
traits_in_scope: FxHashSet<TraitId>,
pub(crate) result: InferenceResult<'db>,
@@ -926,6 +927,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
unstable_features: MethodResolutionUnstableFeatures::from_def_map(
resolver.top_level_def_map(),
),
+ lang_items: table.interner().lang_items(),
edition: resolver.krate().data(db).edition,
table,
tuple_field_accesses_rev: Default::default(),
@@ -1837,21 +1839,13 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
}
- fn resolve_lang_item(&self, item: LangItem) -> Option<LangItemTarget> {
- let krate = self.resolver.krate();
- lang_item(self.db, krate, item)
- }
-
fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
trait_.trait_items(self.db).associated_type_by_name(&Name::new_symbol_root(sym::Output))
}
fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
- let ItemContainerId::TraitId(trait_) = self
- .resolve_lang_item(LangItem::IntoFutureIntoFuture)?
- .as_function()?
- .lookup(self.db)
- .container
+ let ItemContainerId::TraitId(trait_) =
+ self.lang_items.IntoFutureIntoFuture?.lookup(self.db).container
else {
return None;
};
@@ -1859,42 +1853,42 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
fn resolve_boxed_box(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(LangItem::OwnedBox)?.as_struct()?;
+ let struct_ = self.lang_items.OwnedBox?;
Some(struct_.into())
}
fn resolve_range_full(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(LangItem::RangeFull)?.as_struct()?;
+ let struct_ = self.lang_items.RangeFull?;
Some(struct_.into())
}
fn resolve_range(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(LangItem::Range)?.as_struct()?;
+ let struct_ = self.lang_items.Range?;
Some(struct_.into())
}
fn resolve_range_inclusive(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(LangItem::RangeInclusiveStruct)?.as_struct()?;
+ let struct_ = self.lang_items.RangeInclusiveStruct?;
Some(struct_.into())
}
fn resolve_range_from(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(LangItem::RangeFrom)?.as_struct()?;
+ let struct_ = self.lang_items.RangeFrom?;
Some(struct_.into())
}
fn resolve_range_to(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(LangItem::RangeTo)?.as_struct()?;
+ let struct_ = self.lang_items.RangeTo?;
Some(struct_.into())
}
fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(LangItem::RangeToInclusive)?.as_struct()?;
+ let struct_ = self.lang_items.RangeToInclusive?;
Some(struct_.into())
}
fn resolve_va_list(&self) -> Option<AdtId> {
- let struct_ = self.resolve_lang_item(LangItem::VaList)?.as_struct()?;
+ let struct_ = self.lang_items.VaList?;
Some(struct_.into())
}
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 54a06ebd2c..89ebd2b21d 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -7,7 +7,6 @@ use std::{iter, mem, ops::ControlFlow};
use hir_def::{
TraitId,
hir::{ClosureKind, ExprId, PatId},
- lang_item::LangItem,
type_ref::TypeRefId,
};
use rustc_type_ir::{
@@ -220,11 +219,12 @@ impl<'db> InferenceContext<'_, 'db> {
}
fn fn_trait_kind_from_def_id(&self, trait_id: TraitId) -> Option<rustc_type_ir::ClosureKind> {
- let lang_item = self.db.lang_attr(trait_id.into())?;
- match lang_item {
- LangItem::Fn => Some(rustc_type_ir::ClosureKind::Fn),
- LangItem::FnMut => Some(rustc_type_ir::ClosureKind::FnMut),
- LangItem::FnOnce => Some(rustc_type_ir::ClosureKind::FnOnce),
+ match trait_id {
+ _ if self.lang_items.Fn == Some(trait_id) => Some(rustc_type_ir::ClosureKind::Fn),
+ _ if self.lang_items.FnMut == Some(trait_id) => Some(rustc_type_ir::ClosureKind::FnMut),
+ _ if self.lang_items.FnOnce == Some(trait_id) => {
+ Some(rustc_type_ir::ClosureKind::FnOnce)
+ }
_ => None,
}
}
@@ -233,11 +233,14 @@ impl<'db> InferenceContext<'_, 'db> {
&self,
trait_id: TraitId,
) -> Option<rustc_type_ir::ClosureKind> {
- let lang_item = self.db.lang_attr(trait_id.into())?;
- match lang_item {
- LangItem::AsyncFn => Some(rustc_type_ir::ClosureKind::Fn),
- LangItem::AsyncFnMut => Some(rustc_type_ir::ClosureKind::FnMut),
- LangItem::AsyncFnOnce => Some(rustc_type_ir::ClosureKind::FnOnce),
+ match trait_id {
+ _ if self.lang_items.AsyncFn == Some(trait_id) => Some(rustc_type_ir::ClosureKind::Fn),
+ _ if self.lang_items.AsyncFnMut == Some(trait_id) => {
+ Some(rustc_type_ir::ClosureKind::FnMut)
+ }
+ _ if self.lang_items.AsyncFnOnce == Some(trait_id) => {
+ Some(rustc_type_ir::ClosureKind::FnOnce)
+ }
_ => None,
}
}
@@ -433,21 +436,20 @@ impl<'db> InferenceContext<'_, 'db> {
projection: PolyProjectionPredicate<'db>,
) -> Option<PolyFnSig<'db>> {
let SolverDefId::TypeAliasId(def_id) = projection.item_def_id() else { unreachable!() };
- let lang_item = self.db.lang_attr(def_id.into());
// For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits,
// for closures and async closures, respectively.
match closure_kind {
- ClosureKind::Closure if lang_item == Some(LangItem::FnOnceOutput) => {
+ ClosureKind::Closure if Some(def_id) == self.lang_items.FnOnceOutput => {
self.extract_sig_from_projection(projection)
}
- ClosureKind::Async if lang_item == Some(LangItem::AsyncFnOnceOutput) => {
+ ClosureKind::Async if Some(def_id) == self.lang_items.AsyncFnOnceOutput => {
self.extract_sig_from_projection(projection)
}
// It's possible we've passed the closure to a (somewhat out-of-fashion)
// `F: FnOnce() -> Fut, Fut: Future<Output = T>` style bound. Let's still
// guide inference here, since it's beneficial for the user.
- ClosureKind::Async if lang_item == Some(LangItem::FnOnceOutput) => {
+ ClosureKind::Async if Some(def_id) == self.lang_items.FnOnceOutput => {
self.extract_sig_from_projection_and_future_bound(projection)
}
_ => None,
@@ -538,7 +540,7 @@ impl<'db> InferenceContext<'_, 'db> {
&& let ret_projection = bound.predicate.kind().rebind(ret_projection)
&& let Some(ret_projection) = ret_projection.no_bound_vars()
&& let SolverDefId::TypeAliasId(assoc_type) = ret_projection.def_id()
- && self.db.lang_attr(assoc_type.into()) == Some(LangItem::FutureOutput)
+ && Some(assoc_type) == self.lang_items.FutureOutput
{
return_ty = Some(ret_projection.term.expect_type());
break;
diff --git a/crates/hir-ty/src/infer/coerce.rs b/crates/hir-ty/src/infer/coerce.rs
index aeb354368c..3148ef37d8 100644
--- a/crates/hir-ty/src/infer/coerce.rs
+++ b/crates/hir-ty/src/infer/coerce.rs
@@ -38,7 +38,6 @@
use hir_def::{
CallableDefId,
hir::{ExprId, ExprOrPatId},
- lang_item::LangItem,
signatures::FunctionSignature,
};
use intern::sym;
@@ -612,10 +611,8 @@ where
return Err(TypeError::Mismatch);
}
- let traits = (
- LangItem::Unsize.resolve_trait(self.db(), self.env().krate),
- LangItem::CoerceUnsized.resolve_trait(self.db(), self.env().krate),
- );
+ let lang_items = self.interner().lang_items();
+ let traits = (lang_items.Unsize, lang_items.CoerceUnsized);
let (Some(unsize_did), Some(coerce_unsized_did)) = traits else {
debug!("missing Unsize or CoerceUnsized traits");
return Err(TypeError::Mismatch);
diff --git a/crates/hir-ty/src/infer/expr.rs b/crates/hir-ty/src/infer/expr.rs
index 7487660a76..4986bdecfa 100644
--- a/crates/hir-ty/src/infer/expr.rs
+++ b/crates/hir-ty/src/infer/expr.rs
@@ -10,7 +10,6 @@ use hir_def::{
Array, AsmOperand, AsmOptions, BinaryOp, BindingAnnotation, Expr, ExprId, ExprOrPatId,
LabelId, Literal, Pat, PatId, Statement, UnaryOp,
},
- lang_item::{LangItem, LangItemTarget},
resolver::ValueNs,
};
use hir_def::{FunctionId, hir::ClosureKind};
@@ -874,14 +873,10 @@ impl<'db> InferenceContext<'_, 'db> {
Literal::CString(..) => Ty::new_ref(
self.interner(),
self.types.re_static,
- self.resolve_lang_item(LangItem::CStr)
- .and_then(LangItemTarget::as_struct)
- .map_or_else(
- || self.err_ty(),
- |strukt| {
- Ty::new_adt(self.interner(), strukt.into(), self.types.empty_args)
- },
- ),
+ self.lang_items.CStr.map_or_else(
+ || self.err_ty(),
+ |strukt| Ty::new_adt(self.interner(), strukt.into(), self.types.empty_args),
+ ),
Mutability::Not,
),
Literal::Char(..) => self.types.char,
@@ -1279,7 +1274,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
}
}
- let Some(trait_) = fn_x.get_id(self.db, self.table.trait_env.krate) else {
+ let Some(trait_) = fn_x.get_id(self.lang_items) else {
return;
};
let trait_data = trait_.trait_items(self.db);
diff --git a/crates/hir-ty/src/infer/mutability.rs b/crates/hir-ty/src/infer/mutability.rs
index a257547e09..87dcaa8a4e 100644
--- a/crates/hir-ty/src/infer/mutability.rs
+++ b/crates/hir-ty/src/infer/mutability.rs
@@ -18,7 +18,6 @@ impl<'db> InferenceContext<'_, 'db> {
}
fn infer_mut_expr(&mut self, tgt_expr: ExprId, mut mutability: Mutability) {
- let krate = self.krate();
if let Some(adjustments) = self.result.expr_adjustments.get_mut(&tgt_expr) {
let mut adjustments = adjustments.iter_mut().rev().peekable();
while let Some(adj) = adjustments.next() {
@@ -32,7 +31,6 @@ impl<'db> InferenceContext<'_, 'db> {
};
if let Some(infer_ok) = Self::try_mutable_overloaded_place_op(
&self.table,
- krate,
source_ty,
None,
PlaceOp::Deref,
diff --git a/crates/hir-ty/src/infer/op.rs b/crates/hir-ty/src/infer/op.rs
index 88319a8b1a..6fbac8f5ae 100644
--- a/crates/hir-ty/src/infer/op.rs
+++ b/crates/hir-ty/src/infer/op.rs
@@ -2,7 +2,7 @@
use std::collections::hash_map;
-use hir_def::{GenericParamId, TraitId, hir::ExprId, lang_item::LangItem};
+use hir_def::{GenericParamId, TraitId, hir::ExprId};
use intern::{Symbol, sym};
use rustc_ast_ir::Mutability;
use rustc_type_ir::inherent::{IntoKind, Ty as _};
@@ -355,17 +355,18 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
fn lang_item_for_bin_op(&self, op: BinaryOp) -> (Symbol, Option<TraitId>) {
let (method_name, trait_lang_item) =
- crate::lang_items::lang_items_for_bin_op(op).expect("invalid operator provided");
- (method_name, trait_lang_item.resolve_trait(self.db, self.krate()))
+ crate::lang_items::lang_items_for_bin_op(self.lang_items, op)
+ .expect("invalid operator provided");
+ (method_name, trait_lang_item)
}
fn lang_item_for_unop(&self, op: UnaryOp) -> (Symbol, Option<TraitId>) {
let (method_name, trait_lang_item) = match op {
- UnaryOp::Not => (sym::not, LangItem::Not),
- UnaryOp::Neg => (sym::neg, LangItem::Neg),
+ UnaryOp::Not => (sym::not, self.lang_items.Not),
+ UnaryOp::Neg => (sym::neg, self.lang_items.Neg),
UnaryOp::Deref => panic!("Deref is not overloadable"),
};
- (method_name, trait_lang_item.resolve_trait(self.db, self.krate()))
+ (method_name, trait_lang_item)
}
}
diff --git a/crates/hir-ty/src/infer/place_op.rs b/crates/hir-ty/src/infer/place_op.rs
index 50018bb23b..9544fb449f 100644
--- a/crates/hir-ty/src/infer/place_op.rs
+++ b/crates/hir-ty/src/infer/place_op.rs
@@ -1,7 +1,6 @@
//! Inference of *place operators*: deref and indexing (operators that create places, as opposed to values).
-use base_db::Crate;
-use hir_def::{hir::ExprId, lang_item::LangItem};
+use hir_def::hir::ExprId;
use intern::sym;
use rustc_ast_ir::Mutability;
use rustc_type_ir::inherent::{IntoKind, Ty as _};
@@ -187,8 +186,8 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
debug!("try_overloaded_place_op({:?},{:?})", base_ty, op);
let (Some(imm_tr), imm_op) = (match op {
- PlaceOp::Deref => (LangItem::Deref.resolve_trait(self.db, self.krate()), sym::deref),
- PlaceOp::Index => (LangItem::Index.resolve_trait(self.db, self.krate()), sym::index),
+ PlaceOp::Deref => (self.lang_items.Deref, sym::deref),
+ PlaceOp::Index => (self.lang_items.Index, sym::index),
}) else {
// Bail if `Deref` or `Index` isn't defined.
return None;
@@ -209,16 +208,16 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
pub(super) fn try_mutable_overloaded_place_op(
table: &InferenceTable<'db>,
- krate: Crate,
base_ty: Ty<'db>,
opt_rhs_ty: Option<Ty<'db>>,
op: PlaceOp,
) -> Option<InferOk<'db, MethodCallee<'db>>> {
debug!("try_mutable_overloaded_place_op({:?},{:?})", base_ty, op);
+ let lang_items = table.interner().lang_items();
let (Some(mut_tr), mut_op) = (match op {
- PlaceOp::Deref => (LangItem::DerefMut.resolve_trait(table.db, krate), sym::deref_mut),
- PlaceOp::Index => (LangItem::IndexMut.resolve_trait(table.db, krate), sym::index_mut),
+ PlaceOp::Deref => (lang_items.DerefMut, sym::deref_mut),
+ PlaceOp::Index => (lang_items.IndexMut, sym::index_mut),
}) else {
// Bail if `DerefMut` or `IndexMut` isn't defined.
return None;
@@ -276,8 +275,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
))
}
};
- let method =
- Self::try_mutable_overloaded_place_op(&self.table, self.krate(), base_ty, arg_ty, op);
+ let method = Self::try_mutable_overloaded_place_op(&self.table, base_ty, arg_ty, op);
let method = match method {
Some(ok) => self.table.register_infer_ok(ok),
// Couldn't find the mutable variant of the place op, keep the
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index b7187fac68..f25ed3f2e6 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -2,7 +2,7 @@
use std::fmt;
-use hir_def::{AdtId, DefWithBodyId, GenericParamId, lang_item::LangItem};
+use hir_def::{AdtId, DefWithBodyId, GenericParamId};
use hir_expand::name::Name;
use intern::sym;
use rustc_hash::FxHashSet;
@@ -174,7 +174,7 @@ impl<'db> InferenceTable<'db> {
}
pub(crate) fn type_var_is_sized(&self, self_ty: TyVid) -> bool {
- let Some(sized_did) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else {
+ let Some(sized_did) = self.interner().lang_items().Sized else {
return true;
};
self.obligations_for_self_ty(self_ty).into_iter().any(|obligation| {
@@ -520,13 +520,13 @@ impl<'db> InferenceTable<'db> {
ty: Ty<'db>,
num_args: usize,
) -> Option<(FnTrait, Vec<Ty<'db>>, Ty<'db>)> {
+ let lang_items = self.interner().lang_items();
for (fn_trait_name, output_assoc_name, subtraits) in [
(FnTrait::FnOnce, sym::Output, &[FnTrait::Fn, FnTrait::FnMut][..]),
(FnTrait::AsyncFnMut, sym::CallRefFuture, &[FnTrait::AsyncFn]),
(FnTrait::AsyncFnOnce, sym::CallOnceFuture, &[]),
] {
- let krate = self.trait_env.krate;
- let fn_trait = fn_trait_name.get_id(self.db, krate)?;
+ let fn_trait = fn_trait_name.get_id(lang_items)?;
let trait_data = fn_trait.trait_items(self.db);
let output_assoc_type =
trait_data.associated_type_by_name(&Name::new_symbol_root(output_assoc_name))?;
@@ -558,7 +558,7 @@ impl<'db> InferenceTable<'db> {
self.register_obligation(pred);
let return_ty = self.normalize_alias_ty(projection);
for &fn_x in subtraits {
- let fn_x_trait = fn_x.get_id(self.db, krate)?;
+ let fn_x_trait = fn_x.get_id(lang_items)?;
let trait_ref = TraitRef::new(self.interner(), fn_x_trait.into(), args);
let pred = Predicate::upcast_from(trait_ref, self.interner());
if !self.try_obligation(pred).no_solution() {
@@ -658,7 +658,7 @@ impl<'db> InferenceTable<'db> {
}
}
- let Some(sized) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else {
+ let Some(sized) = self.interner().lang_items().Sized else {
return false;
};
let sized_pred = Predicate::upcast_from(
diff --git a/crates/hir-ty/src/lang_items.rs b/crates/hir-ty/src/lang_items.rs
index d0d0aa7a90..18feb0f46a 100644
--- a/crates/hir-ty/src/lang_items.rs
+++ b/crates/hir-ty/src/lang_items.rs
@@ -1,6 +1,6 @@
//! Functions to detect special lang items
-use hir_def::{AdtId, lang_item::LangItem, signatures::StructFlags};
+use hir_def::{AdtId, TraitId, lang_item::LangItems, signatures::StructFlags};
use intern::{Symbol, sym};
use crate::db::HirDatabase;
@@ -10,48 +10,51 @@ pub fn is_box(db: &dyn HirDatabase, adt: AdtId) -> bool {
db.struct_signature(id).flags.contains(StructFlags::IS_BOX)
}
-pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Symbol, LangItem)> {
+pub fn lang_items_for_bin_op(
+ lang_items: &LangItems,
+ op: syntax::ast::BinaryOp,
+) -> Option<(Symbol, Option<TraitId>)> {
use syntax::ast::{ArithOp, BinaryOp, CmpOp, Ordering};
Some(match op {
BinaryOp::LogicOp(_) => return None,
BinaryOp::ArithOp(aop) => match aop {
- ArithOp::Add => (sym::add, LangItem::Add),
- ArithOp::Mul => (sym::mul, LangItem::Mul),
- ArithOp::Sub => (sym::sub, LangItem::Sub),
- ArithOp::Div => (sym::div, LangItem::Div),
- ArithOp::Rem => (sym::rem, LangItem::Rem),
- ArithOp::Shl => (sym::shl, LangItem::Shl),
- ArithOp::Shr => (sym::shr, LangItem::Shr),
- ArithOp::BitXor => (sym::bitxor, LangItem::BitXor),
- ArithOp::BitOr => (sym::bitor, LangItem::BitOr),
- ArithOp::BitAnd => (sym::bitand, LangItem::BitAnd),
+ ArithOp::Add => (sym::add, lang_items.Add),
+ ArithOp::Mul => (sym::mul, lang_items.Mul),
+ ArithOp::Sub => (sym::sub, lang_items.Sub),
+ ArithOp::Div => (sym::div, lang_items.Div),
+ ArithOp::Rem => (sym::rem, lang_items.Rem),
+ ArithOp::Shl => (sym::shl, lang_items.Shl),
+ ArithOp::Shr => (sym::shr, lang_items.Shr),
+ ArithOp::BitXor => (sym::bitxor, lang_items.BitXor),
+ ArithOp::BitOr => (sym::bitor, lang_items.BitOr),
+ ArithOp::BitAnd => (sym::bitand, lang_items.BitAnd),
},
BinaryOp::Assignment { op: Some(aop) } => match aop {
- ArithOp::Add => (sym::add_assign, LangItem::AddAssign),
- ArithOp::Mul => (sym::mul_assign, LangItem::MulAssign),
- ArithOp::Sub => (sym::sub_assign, LangItem::SubAssign),
- ArithOp::Div => (sym::div_assign, LangItem::DivAssign),
- ArithOp::Rem => (sym::rem_assign, LangItem::RemAssign),
- ArithOp::Shl => (sym::shl_assign, LangItem::ShlAssign),
- ArithOp::Shr => (sym::shr_assign, LangItem::ShrAssign),
- ArithOp::BitXor => (sym::bitxor_assign, LangItem::BitXorAssign),
- ArithOp::BitOr => (sym::bitor_assign, LangItem::BitOrAssign),
- ArithOp::BitAnd => (sym::bitand_assign, LangItem::BitAndAssign),
+ ArithOp::Add => (sym::add_assign, lang_items.AddAssign),
+ ArithOp::Mul => (sym::mul_assign, lang_items.MulAssign),
+ ArithOp::Sub => (sym::sub_assign, lang_items.SubAssign),
+ ArithOp::Div => (sym::div_assign, lang_items.DivAssign),
+ ArithOp::Rem => (sym::rem_assign, lang_items.RemAssign),
+ ArithOp::Shl => (sym::shl_assign, lang_items.ShlAssign),
+ ArithOp::Shr => (sym::shr_assign, lang_items.ShrAssign),
+ ArithOp::BitXor => (sym::bitxor_assign, lang_items.BitXorAssign),
+ ArithOp::BitOr => (sym::bitor_assign, lang_items.BitOrAssign),
+ ArithOp::BitAnd => (sym::bitand_assign, lang_items.BitAndAssign),
},
BinaryOp::CmpOp(cop) => match cop {
- CmpOp::Eq { negated: false } => (sym::eq, LangItem::PartialEq),
- CmpOp::Eq { negated: true } => (sym::ne, LangItem::PartialEq),
+ CmpOp::Eq { negated: false } => (sym::eq, lang_items.PartialEq),
+ CmpOp::Eq { negated: true } => (sym::ne, lang_items.PartialEq),
CmpOp::Ord { ordering: Ordering::Less, strict: false } => {
- (sym::le, LangItem::PartialOrd)
+ (sym::le, lang_items.PartialOrd)
}
CmpOp::Ord { ordering: Ordering::Less, strict: true } => {
- (sym::lt, LangItem::PartialOrd)
+ (sym::lt, lang_items.PartialOrd)
}
CmpOp::Ord { ordering: Ordering::Greater, strict: false } => {
- (sym::ge, LangItem::PartialOrd)
+ (sym::ge, lang_items.PartialOrd)
}
CmpOp::Ord { ordering: Ordering::Greater, strict: true } => {
- (sym::gt, LangItem::PartialOrd)
+ (sym::gt, lang_items.PartialOrd)
}
},
BinaryOp::Assignment { op: None } => return None,
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index 8819307c53..6d3adec6a8 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -477,14 +477,14 @@ pub fn callable_sig_from_fn_trait<'db>(
trait_env: Arc<TraitEnvironment<'db>>,
db: &'db dyn HirDatabase,
) -> Option<(FnTrait, PolyFnSig<'db>)> {
- let krate = trait_env.krate;
- let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
+ let mut table = InferenceTable::new(db, trait_env.clone(), None);
+ let lang_items = table.interner().lang_items();
+
+ let fn_once_trait = FnTrait::FnOnce.get_id(lang_items)?;
let output_assoc_type = fn_once_trait
.trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
- let mut table = InferenceTable::new(db, trait_env.clone(), None);
-
// Register two obligations:
// - Self: FnOnce<?args_ty>
// - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
@@ -502,7 +502,7 @@ pub fn callable_sig_from_fn_trait<'db>(
table.register_obligation(pred);
let return_ty = table.normalize_alias_ty(projection);
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
- let fn_x_trait = fn_x.get_id(db, krate)?;
+ let fn_x_trait = fn_x.get_id(lang_items)?;
let trait_ref = TraitRef::new(table.interner(), fn_x_trait.into(), args);
if !table
.try_obligation(Predicate::upcast_from(trait_ref, table.interner()))
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 59e1801483..72e622bcb5 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -11,7 +11,6 @@ pub(crate) mod path;
use std::{cell::OnceCell, iter, mem};
use arrayvec::ArrayVec;
-use base_db::Crate;
use either::Either;
use hir_def::{
AdtId, AssocItemId, CallableDefId, ConstId, ConstParamId, DefWithBodyId, EnumId, EnumVariantId,
@@ -24,7 +23,7 @@ use hir_def::{
GenericParamDataRef, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
},
item_tree::FieldsShape,
- lang_item::LangItem,
+ lang_item::LangItems,
resolver::{HasResolver, LifetimeNs, Resolver, TypeNs, ValueNs},
signatures::{FunctionSignature, TraitFlags, TypeAliasFlags},
type_ref::{
@@ -166,6 +165,7 @@ impl<'db> LifetimeElisionKind<'db> {
pub struct TyLoweringContext<'db, 'a> {
pub db: &'db dyn HirDatabase,
interner: DbInterner<'db>,
+ lang_items: &'db LangItems,
resolver: &'a Resolver<'db>,
store: &'a ExpressionStore,
def: GenericDefId,
@@ -194,6 +194,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
Self {
db,
interner: DbInterner::new_no_crate(db),
+ lang_items: hir_def::lang_item::lang_items(db, resolver.krate()),
resolver,
def,
generics: Default::default(),
@@ -490,7 +491,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
// away instead of two.
let actual_opaque_type_data = self
.with_debruijn(DebruijnIndex::ZERO, |ctx| {
- ctx.lower_impl_trait(opaque_ty_id, bounds, self.resolver.krate())
+ ctx.lower_impl_trait(opaque_ty_id, bounds)
});
self.impl_trait_mode.opaque_type_data[idx] = actual_opaque_type_data;
@@ -658,6 +659,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
ignore_bindings: bool,
) -> impl Iterator<Item = Clause<'db>> + use<'b, 'a, 'db> {
let interner = self.interner;
+ let meta_sized = self.lang_items.MetaSized;
+ let pointee_sized = self.lang_items.PointeeSized;
let mut assoc_bounds = None;
let mut clause = None;
match bound {
@@ -666,10 +669,6 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) {
// FIXME(sized-hierarchy): Remove this bound modifications once we have implemented
// sized-hierarchy correctly.
- let meta_sized = LangItem::MetaSized
- .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
- let pointee_sized = LangItem::PointeeSized
- .resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) {
// Ignore this bound
} else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) {
@@ -692,7 +691,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
}
&TypeBound::Path(path, TraitBoundModifier::Maybe) => {
- let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate());
+ let sized_trait = self.lang_items.Sized;
// 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.
@@ -873,12 +872,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
}
- fn lower_impl_trait(
- &mut self,
- def_id: SolverDefId,
- bounds: &[TypeBound],
- krate: Crate,
- ) -> ImplTrait<'db> {
+ fn lower_impl_trait(&mut self, def_id: SolverDefId, bounds: &[TypeBound]) -> ImplTrait<'db> {
let interner = self.interner;
cov_mark::hit!(lower_rpit);
let args = GenericArgs::identity_for_item(interner, def_id);
@@ -894,7 +888,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
if !ctx.unsized_types.contains(&self_ty) {
- let sized_trait = LangItem::Sized.resolve_trait(self.db, krate);
+ let sized_trait = self.lang_items.Sized;
let sized_clause = sized_trait.map(|trait_id| {
let trait_ref = TraitRef::new_from_args(
interner,
@@ -1400,9 +1394,7 @@ pub(crate) fn generic_predicates_for_param<'db>(
let TypeRef::Path(path) = &ctx.store[path.type_ref()] else {
return false;
};
- let Some(pointee_sized) =
- LangItem::PointeeSized.resolve_trait(ctx.db, ctx.resolver.krate())
- else {
+ let Some(pointee_sized) = ctx.lang_items.PointeeSized else {
return false;
};
// Lower the path directly with `Resolver` instead of PathLoweringContext`
@@ -1465,9 +1457,13 @@ pub(crate) fn generic_predicates_for_param<'db>(
let args = GenericArgs::identity_for_item(interner, def.into());
if !args.is_empty() {
let explicitly_unsized_tys = ctx.unsized_types;
- if let Some(implicitly_sized_predicates) =
- implicitly_sized_clauses(db, param_id.parent, &explicitly_unsized_tys, &args, &resolver)
- {
+ if let Some(implicitly_sized_predicates) = implicitly_sized_clauses(
+ db,
+ ctx.lang_items,
+ param_id.parent,
+ &explicitly_unsized_tys,
+ &args,
+ ) {
predicates.extend(implicitly_sized_predicates);
};
}
@@ -1519,7 +1515,7 @@ pub fn type_alias_bounds_with_diagnostics<'db>(
}
if !ctx.unsized_types.contains(&interner_ty) {
- let sized_trait = LangItem::Sized.resolve_trait(ctx.db, resolver.krate());
+ let sized_trait = ctx.lang_items.Sized;
if let Some(sized_trait) = sized_trait {
let trait_ref = TraitRef::new_from_args(
interner,
@@ -1623,7 +1619,7 @@ pub(crate) fn trait_environment_query<'db>(
def: GenericDefId,
) -> Arc<TraitEnvironment<'db>> {
let module = def.module(db);
- let interner = DbInterner::new_no_crate(db);
+ let interner = DbInterner::new_with(db, module.krate(), module.containing_block());
let predicates = GenericPredicates::query_all(db, def);
let traits_in_scope = predicates
.iter_identity_copied()
@@ -1669,7 +1665,7 @@ where
def,
LifetimeElisionKind::AnonymousReportError,
);
- let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate());
+ let sized_trait = ctx.lang_items.Sized;
let mut predicates = Vec::new();
let all_generics =
@@ -1837,13 +1833,13 @@ fn push_const_arg_has_type_predicates<'db>(
/// Exception is Self of a trait def.
fn implicitly_sized_clauses<'a, 'subst, 'db>(
db: &'db dyn HirDatabase,
+ lang_items: &LangItems,
def: GenericDefId,
explicitly_unsized_tys: &'a FxHashSet<Ty<'db>>,
args: &'subst GenericArgs<'db>,
- resolver: &Resolver<'db>,
) -> Option<impl Iterator<Item = Clause<'db>> + Captures<'a> + Captures<'subst>> {
let interner = DbInterner::new_no_crate(db);
- let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate())?;
+ let sized_trait = lang_items.Sized?;
let trait_self_idx = trait_self_param_idx(db, def);
@@ -2137,7 +2133,7 @@ pub(crate) fn associated_ty_item_bounds<'db>(
}
if !ctx.unsized_types.contains(&self_ty)
- && let Some(sized_trait) = LangItem::Sized.resolve_trait(db, resolver.krate())
+ && let Some(sized_trait) = ctx.lang_items.Sized
{
let sized_clause = Binder::dummy(ExistentialPredicate::Trait(ExistentialTraitRef::new(
interner,
@@ -2155,7 +2151,8 @@ pub(crate) fn associated_type_by_name_including_super_traits<'db>(
trait_ref: TraitRef<'db>,
name: &Name,
) -> Option<(TraitRef<'db>, TypeAliasId)> {
- let interner = DbInterner::new_no_crate(db);
+ let module = trait_ref.def_id.0.module(db);
+ let interner = DbInterner::new_with(db, module.krate(), module.containing_block());
rustc_type_ir::elaborate::supertraits(interner, Binder::dummy(trait_ref)).find_map(|t| {
let trait_id = t.as_ref().skip_binder().def_id.0;
let assoc_type = trait_id.trait_items(db).associated_type_by_name(name)?;
diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs
index 9e8791edde..05a957b93d 100644
--- a/crates/hir-ty/src/method_resolution/confirm.rs
+++ b/crates/hir-ty/src/method_resolution/confirm.rs
@@ -5,7 +5,6 @@ use hir_def::{
FunctionId, GenericDefId, GenericParamId, ItemContainerId, TraitId,
expr_store::path::{GenericArg as HirGenericArg, GenericArgs as HirGenericArgs},
hir::{ExprId, generics::GenericParamDataRef},
- lang_item::LangItem,
};
use rustc_type_ir::{
TypeFoldable,
@@ -550,9 +549,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
&self,
predicates: impl Iterator<Item = Clause<'db>>,
) -> bool {
- let Some(sized_def_id) =
- LangItem::Sized.resolve_trait(self.db(), self.ctx.resolver.krate())
- else {
+ let Some(sized_def_id) = self.ctx.lang_items.Sized else {
return false;
};
@@ -570,9 +567,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
fn check_for_illegal_method_calls(&self) {
// Disallow calls to the method `drop` defined in the `Drop` trait.
if let ItemContainerId::TraitId(trait_def_id) = self.candidate.loc(self.db()).container
- && LangItem::Drop
- .resolve_trait(self.db(), self.ctx.resolver.krate())
- .is_some_and(|drop_trait| drop_trait == trait_def_id)
+ && self.ctx.lang_items.Drop.is_some_and(|drop_trait| drop_trait == trait_def_id)
{
// FIXME: Report an error.
}
diff --git a/crates/hir-ty/src/mir/eval.rs b/crates/hir-ty/src/mir/eval.rs
index ba89b71d9d..7e3a120c06 100644
--- a/crates/hir-ty/src/mir/eval.rs
+++ b/crates/hir-ty/src/mir/eval.rs
@@ -9,7 +9,7 @@ use hir_def::{
Lookup, StaticId, VariantId,
expr_store::HygieneId,
item_tree::FieldsShape,
- lang_item::LangItem,
+ lang_item::LangItems,
layout::{TagEncoding, Variants},
resolver::{HasResolver, TypeNs, ValueNs},
signatures::{StaticFlags, StructFlags},
@@ -643,6 +643,7 @@ impl<'db> Evaluator<'db> {
let cached_ptr_size = target_data_layout.pointer_size().bytes_usize();
let interner = DbInterner::new_with(db, crate_id, module.containing_block());
let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
+ let lang_items = interner.lang_items();
Ok(Evaluator {
target_data_layout,
stack: vec![0],
@@ -667,13 +668,13 @@ impl<'db> Evaluator<'db> {
mir_or_dyn_index_cache: RefCell::new(Default::default()),
unused_locals_store: RefCell::new(Default::default()),
cached_ptr_size,
- cached_fn_trait_func: LangItem::Fn
- .resolve_trait(db, crate_id)
+ cached_fn_trait_func: lang_items
+ .Fn
.and_then(|x| x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call))),
- cached_fn_mut_trait_func: LangItem::FnMut.resolve_trait(db, crate_id).and_then(|x| {
+ cached_fn_mut_trait_func: lang_items.FnMut.and_then(|x| {
x.trait_items(db).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| {
+ cached_fn_once_trait_func: lang_items.FnOnce.and_then(|x| {
x.trait_items(db).method_by_name(&Name::new_symbol_root(sym::call_once))
}),
infcx,
@@ -685,6 +686,11 @@ impl<'db> Evaluator<'db> {
self.infcx.interner
}
+ #[inline]
+ fn lang_items(&self) -> &'db LangItems {
+ self.infcx.interner.lang_items()
+ }
+
fn place_addr(&self, p: &Place<'db>, locals: &Locals<'db>) -> Result<'db, Address> {
Ok(self.place_addr_and_ty_and_metadata(p, locals)?.0)
}
@@ -2864,7 +2870,7 @@ impl<'db> Evaluator<'db> {
span: MirSpan,
) -> Result<'db, ()> {
let Some(drop_fn) = (|| {
- let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?;
+ let drop_trait = self.lang_items().Drop?;
drop_trait.trait_items(self.db).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/crates/hir-ty/src/mir/eval/shim.rs b/crates/hir-ty/src/mir/eval/shim.rs
index 4b1adecf8c..c61afd62c4 100644
--- a/crates/hir-ty/src/mir/eval/shim.rs
+++ b/crates/hir-ty/src/mir/eval/shim.rs
@@ -3,7 +3,7 @@
//!
use std::cmp::{self, Ordering};
-use hir_def::{CrateRootModuleId, resolver::HasResolver, signatures::FunctionSignature};
+use hir_def::signatures::FunctionSignature;
use hir_expand::name::Name;
use intern::{Symbol, sym};
use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike, Ty as _};
@@ -14,8 +14,8 @@ use crate::{
drop::{DropGlue, has_drop_glue},
mir::eval::{
Address, AdtId, Arc, Evaluator, FunctionId, GenericArgs, HasModule, HirDisplay,
- InternedClosure, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId, LangItem,
- Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Ty, TyKind, pad16,
+ InternedClosure, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId, Layout, Locals,
+ Lookup, MirEvalError, MirSpan, Mutability, Result, Ty, TyKind, pad16,
},
next_solver::Region,
};
@@ -38,6 +38,13 @@ macro_rules! not_supported {
};
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum EvalLangItem {
+ BeginPanic,
+ SliceLen,
+ DropInPlace,
+}
+
impl<'db> Evaluator<'db> {
pub(super) fn detect_and_exec_special_function(
&mut self,
@@ -105,7 +112,7 @@ impl<'db> Evaluator<'db> {
return Ok(true);
}
if let ItemContainerId::TraitId(t) = def.lookup(self.db).container
- && self.db.lang_attr(t.into()) == Some(LangItem::Clone)
+ && Some(t) == self.lang_items().Clone
{
let [self_ty] = generic_args.as_slice() else {
not_supported!("wrong generic arg count for clone");
@@ -131,12 +138,8 @@ impl<'db> Evaluator<'db> {
def: FunctionId,
) -> Result<'db, Option<FunctionId>> {
// `PanicFmt` is redirected to `ConstPanicFmt`
- if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
- let resolver = CrateRootModuleId::from(self.crate_id).resolver(self.db);
-
- let Some(const_panic_fmt) =
- LangItem::ConstPanicFmt.resolve_function(self.db, resolver.krate())
- else {
+ if Some(def) == self.lang_items().PanicFmt {
+ let Some(const_panic_fmt) = self.lang_items().ConstPanicFmt else {
not_supported!("const_panic_fmt lang item not found or not a function");
};
return Ok(Some(const_panic_fmt));
@@ -286,19 +289,26 @@ impl<'db> Evaluator<'db> {
Ok(())
}
- fn detect_lang_function(&self, def: FunctionId) -> Option<LangItem> {
- use LangItem::*;
+ fn detect_lang_function(&self, def: FunctionId) -> Option<EvalLangItem> {
+ use EvalLangItem::*;
+ let lang_items = self.lang_items();
let attrs = self.db.attrs(def.into());
if attrs.by_key(sym::rustc_const_panic_str).exists() {
// `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
- return Some(LangItem::BeginPanic);
+ return Some(BeginPanic);
}
- let candidate = attrs.lang_item()?;
// We want to execute these functions with special logic
// `PanicFmt` is not detected here as it's redirected later.
- if [BeginPanic, SliceLen, DropInPlace].contains(&candidate) {
+ if let Some((_, candidate)) = [
+ (lang_items.BeginPanic, BeginPanic),
+ (lang_items.SliceLen, SliceLen),
+ (lang_items.DropInPlace, DropInPlace),
+ ]
+ .iter()
+ .find(|&(candidate, _)| candidate == Some(def))
+ {
return Some(candidate);
}
@@ -307,13 +317,13 @@ impl<'db> Evaluator<'db> {
fn exec_lang_item(
&mut self,
- it: LangItem,
+ it: EvalLangItem,
generic_args: GenericArgs<'db>,
args: &[IntervalAndTy<'db>],
locals: &Locals<'db>,
span: MirSpan,
) -> Result<'db, Vec<u8>> {
- use LangItem::*;
+ use EvalLangItem::*;
let mut args = args.iter();
match it {
BeginPanic => {
@@ -374,7 +384,6 @@ impl<'db> Evaluator<'db> {
)?;
Ok(vec![])
}
- it => not_supported!("Executing lang item {it:?}"),
}
}
@@ -1219,7 +1228,7 @@ impl<'db> Evaluator<'db> {
let addr = tuple.interval.addr.offset(offset);
args.push(IntervalAndTy::new(addr, field, self, locals)?);
}
- if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id)
+ if let Some(target) = self.lang_items().FnOnce
&& let Some(def) = target
.trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::call_once))
@@ -1329,7 +1338,7 @@ impl<'db> Evaluator<'db> {
{
result = (l as i8).cmp(&(r as i8));
}
- if let Some(e) = LangItem::Ordering.resolve_enum(self.db, self.crate_id) {
+ if let Some(e) = self.lang_items().Ordering {
let ty = self.db.ty(e.into()).skip_binder();
let r = self.compute_discriminant(ty, &[result as i8 as u8])?;
destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size])?;
diff --git a/crates/hir-ty/src/mir/lower.rs b/crates/hir-ty/src/mir/lower.rs
index 9037fdf57c..be2291a62c 100644
--- a/crates/hir-ty/src/mir/lower.rs
+++ b/crates/hir-ty/src/mir/lower.rs
@@ -12,7 +12,7 @@ use hir_def::{
Pat, PatId, RecordFieldPat, RecordLitField,
},
item_tree::FieldsShape,
- lang_item::{LangItem, LangItemTarget, lang_item},
+ lang_item::LangItems,
resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
};
use hir_expand::name::Name;
@@ -110,7 +110,7 @@ pub enum MirLowerError<'db> {
Loop,
/// Something that should never happen and is definitely a bug, but we don't want to panic if it happened
ImplementationError(String),
- LangItemNotFound(LangItem),
+ LangItemNotFound,
MutatingRvalue,
UnresolvedLabel,
UnresolvedUpvar(Place<'db>),
@@ -232,7 +232,7 @@ impl MirLowerError<'_> {
| MirLowerError::BreakWithoutLoop
| MirLowerError::Loop
| MirLowerError::ImplementationError(_)
- | MirLowerError::LangItemNotFound(_)
+ | MirLowerError::LangItemNotFound
| MirLowerError::MutatingRvalue
| MirLowerError::UnresolvedLabel
| MirLowerError::UnresolvedUpvar(_) => writeln!(f, "{self:?}")?,
@@ -327,6 +327,11 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
self.infcx.interner
}
+ #[inline]
+ fn lang_items(&self) -> &'db LangItems {
+ self.infcx.interner.lang_items()
+ }
+
fn temp(
&mut self,
ty: Ty<'db>,
@@ -1816,11 +1821,6 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> {
Ok(())
}
- fn resolve_lang_item(&self, item: LangItem) -> Result<'db, LangItemTarget> {
- let crate_id = self.owner.module(self.db).krate();
- lang_item(self.db, crate_id, item).ok_or(MirLowerError::LangItemNotFound(item))
- }
-
fn lower_block_to_place(
&mut self,
statements: &[hir_def::hir::Statement],
diff --git a/crates/hir-ty/src/mir/lower/as_place.rs b/crates/hir-ty/src/mir/lower/as_place.rs
index bceafae0f1..40c6c5de79 100644
--- a/crates/hir-ty/src/mir/lower/as_place.rs
+++ b/crates/hir-ty/src/mir/lower/as_place.rs
@@ -2,7 +2,7 @@
use hir_def::FunctionId;
use intern::sym;
-use rustc_type_ir::inherent::{AdtDef, Region as _, Ty as _};
+use rustc_type_ir::inherent::{Region as _, Ty as _};
use super::*;
use crate::{
@@ -177,13 +177,7 @@ impl<'db> MirLowerCtx<'_, 'db> {
Expr::UnaryOp { expr, op: hir_def::hir::UnaryOp::Deref } => {
let is_builtin = match self.expr_ty_without_adjust(*expr).kind() {
TyKind::Ref(..) | TyKind::RawPtr(..) => true,
- TyKind::Adt(id, _) => {
- if let Some(lang_item) = self.db.lang_attr(id.def_id().0.into()) {
- lang_item == LangItem::OwnedBox
- } else {
- false
- }
- }
+ TyKind::Adt(id, _) => id.is_box(),
_ => false,
};
if !is_builtin {
@@ -198,8 +192,7 @@ impl<'db> MirLowerCtx<'_, 'db> {
expr_id.into(),
'b: {
if let Some((f, _)) = self.infer.method_resolution(expr_id)
- && let Some(deref_trait) =
- self.resolve_lang_item(LangItem::DerefMut)?.as_trait()
+ && let Some(deref_trait) = self.lang_items().DerefMut
&& let Some(deref_fn) = deref_trait
.trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::deref_mut))
@@ -330,17 +323,18 @@ impl<'db> MirLowerCtx<'_, 'db> {
span: MirSpan,
mutability: bool,
) -> Result<'db, Option<(Place<'db>, BasicBlockId<'db>)>> {
+ let lang_items = self.lang_items();
let (mutability, trait_lang_item, trait_method_name, borrow_kind) = if !mutability {
(
Mutability::Not,
- LangItem::Deref,
+ lang_items.Deref,
Name::new_symbol_root(sym::deref),
BorrowKind::Shared,
)
} else {
(
Mutability::Mut,
- LangItem::DerefMut,
+ lang_items.DerefMut,
Name::new_symbol_root(sym::deref_mut),
BorrowKind::Mut { kind: MutBorrowKind::Default },
)
@@ -350,14 +344,11 @@ impl<'db> MirLowerCtx<'_, 'db> {
let target_ty_ref = Ty::new_ref(self.interner(), error_region, target_ty, mutability);
let ref_place: Place<'db> = self.temp(ty_ref, current, span)?.into();
self.push_assignment(current, ref_place, Rvalue::Ref(borrow_kind, place), span);
- let deref_trait = self
- .resolve_lang_item(trait_lang_item)?
- .as_trait()
- .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
+ let deref_trait = trait_lang_item.ok_or(MirLowerError::LangItemNotFound)?;
let deref_fn = deref_trait
.trait_items(self.db)
.method_by_name(&trait_method_name)
- .ok_or(MirLowerError::LangItemNotFound(trait_lang_item))?;
+ .ok_or(MirLowerError::LangItemNotFound)?;
let deref_fn_op = Operand::const_zst(Ty::new_fn_def(
self.interner(),
CallableDefId::FunctionId(deref_fn).into(),
diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs
index fcce04fb08..443191423a 100644
--- a/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/mod.rs
@@ -8,7 +8,6 @@ use std::sync::Arc;
pub use BoundRegionConversionTime::*;
use ena::unify as ut;
use hir_def::GenericParamId;
-use hir_def::lang_item::LangItem;
use opaque_types::{OpaqueHiddenType, OpaqueTypeStorage};
use region_constraints::{RegionConstraintCollector, RegionConstraintStorage};
use rustc_next_trait_solver::solve::SolverDelegateEvalExt;
@@ -542,9 +541,7 @@ impl<'db> InferCtxt<'db> {
pub fn type_is_copy_modulo_regions(&self, param_env: ParamEnv<'db>, ty: Ty<'db>) -> bool {
let ty = self.resolve_vars_if_possible(ty);
- let Some(copy_def_id) =
- LangItem::Copy.resolve_trait(self.interner.db, self.interner.krate.unwrap())
- else {
+ let Some(copy_def_id) = self.interner.lang_items().Copy else {
return false;
};
diff --git a/crates/hir-ty/src/next_solver/interner.rs b/crates/hir-ty/src/next_solver/interner.rs
index a62835d9b0..82c4235b2f 100644
--- a/crates/hir-ty/src/next_solver/interner.rs
+++ b/crates/hir-ty/src/next_solver/interner.rs
@@ -8,9 +8,9 @@ pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db};
use base_db::Crate;
use hir_def::{
- AdtId, AttrDefId, BlockId, CallableDefId, DefWithBodyId, EnumVariantId, HasModule,
- ItemContainerId, StructId, UnionId, VariantId,
- lang_item::LangItem,
+ AdtId, BlockId, CallableDefId, DefWithBodyId, EnumVariantId, HasModule, ItemContainerId,
+ StructId, UnionId, VariantId,
+ lang_item::LangItems,
signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags},
};
use la_arena::Idx;
@@ -272,6 +272,7 @@ pub struct DbInterner<'db> {
pub(crate) db: &'db dyn HirDatabase,
pub(crate) krate: Option<Crate>,
pub(crate) block: Option<BlockId>,
+ lang_items: Option<&'db LangItems>,
}
// FIXME: very wrong, see https://github.com/rust-lang/rust/pull/144808
@@ -285,13 +286,17 @@ impl<'db> DbInterner<'db> {
db: unsafe { std::mem::transmute::<&dyn HirDatabase, &'db dyn HirDatabase>(db) },
krate: None,
block: None,
+ lang_items: None,
})
}
/// Creates a new interner without an active crate. Good only for interning things, not for trait solving etc..
/// As a rule of thumb, when you create an `InferCtxt`, you need to provide the crate (and the block).
+ ///
+ /// Elaboration is a special kind: it needs lang items (for `Sized`), therefore it needs `new_with()`, but you
+ /// can not specify the block.
pub fn new_no_crate(db: &'db dyn HirDatabase) -> Self {
- DbInterner { db, krate: None, block: None }
+ DbInterner { db, krate: None, block: None, lang_items: None }
}
pub fn new_with(
@@ -299,13 +304,30 @@ impl<'db> DbInterner<'db> {
krate: Crate,
block: Option<BlockId>,
) -> DbInterner<'db> {
- DbInterner { db, krate: Some(krate), block }
+ DbInterner {
+ db,
+ krate: Some(krate),
+ block,
+ // As an approximation, when we call `new_with` we're trait solving, therefore we need the lang items.
+ // This is also convenient since here we have a starting crate but not in `new_no_crate`.
+ lang_items: Some(hir_def::lang_item::lang_items(db, krate)),
+ }
}
#[inline]
pub fn db(&self) -> &'db dyn HirDatabase {
self.db
}
+
+ #[inline]
+ #[track_caller]
+ pub fn lang_items(&self) -> &'db LangItems {
+ self.lang_items.expect(
+ "Must have `DbInterner::lang_items`.\n\n\
+ Note: you might have called `DbInterner::new_no_crate()` \
+ where you should've called `DbInterner::new_with()`",
+ )
+ }
}
// This is intentionally left as `()`
@@ -855,7 +877,7 @@ interned_vec_db!(PatList, Pattern);
macro_rules! as_lang_item {
(
- $solver_enum:ident, $var:ident;
+ $solver_enum:ident, $self:ident, $def_id:expr;
ignore = {
$( $ignore:ident ),* $(,)?
@@ -863,6 +885,7 @@ macro_rules! as_lang_item {
$( $variant:ident ),* $(,)?
) => {{
+ let lang_items = $self.lang_items();
// Ensure exhaustiveness.
if let Some(it) = None::<$solver_enum> {
match it {
@@ -870,13 +893,32 @@ macro_rules! as_lang_item {
$( $solver_enum::$ignore => {} )*
}
}
- match $var {
- $( LangItem::$variant => Some($solver_enum::$variant), )*
+ match $def_id {
+ $( def_id if lang_items.$variant.is_some_and(|it| it == def_id) => Some($solver_enum::$variant), )*
_ => None
}
}};
}
+macro_rules! is_lang_item {
+ (
+ $solver_enum:ident, $self:ident, $def_id:expr, $expected_variant:ident;
+
+ ignore = {
+ $( $ignore:ident ),* $(,)?
+ }
+
+ $( $variant:ident ),* $(,)?
+ ) => {{
+ let lang_items = $self.lang_items();
+ let def_id = $def_id;
+ match $expected_variant {
+ $( $solver_enum::$variant => lang_items.$variant.is_some_and(|it| it == def_id), )*
+ $( $solver_enum::$ignore => false, )*
+ }
+ }};
+}
+
impl<'db> Interner for DbInterner<'db> {
type DefId = SolverDefId;
type LocalDefId = SolverDefId;
@@ -1259,8 +1301,7 @@ impl<'db> Interner for DbInterner<'db> {
}
fn generics_require_sized_self(self, def_id: Self::DefId) -> bool {
- let sized_trait =
- LangItem::Sized.resolve_trait(self.db(), self.krate.expect("Must have self.krate"));
+ let sized_trait = self.lang_items().Sized;
let Some(sized_id) = sized_trait else {
return false; /* No Sized trait, can't require it! */
};
@@ -1434,84 +1475,69 @@ impl<'db> Interner for DbInterner<'db> {
}
fn require_lang_item(self, lang_item: SolverLangItem) -> Self::DefId {
+ let lang_items = self.lang_items();
let lang_item = match lang_item {
SolverLangItem::AsyncFnKindUpvars => unimplemented!(),
- SolverLangItem::AsyncFnOnceOutput => LangItem::AsyncFnOnceOutput,
- SolverLangItem::CallOnceFuture => LangItem::CallOnceFuture,
- SolverLangItem::CallRefFuture => LangItem::CallRefFuture,
- SolverLangItem::CoroutineReturn => LangItem::CoroutineReturn,
- SolverLangItem::CoroutineYield => LangItem::CoroutineYield,
- SolverLangItem::DynMetadata => LangItem::DynMetadata,
- SolverLangItem::FutureOutput => LangItem::FutureOutput,
- SolverLangItem::Metadata => LangItem::Metadata,
+ SolverLangItem::AsyncFnOnceOutput => lang_items.AsyncFnOnceOutput,
+ SolverLangItem::CallOnceFuture => lang_items.CallOnceFuture,
+ SolverLangItem::CallRefFuture => lang_items.CallRefFuture,
+ SolverLangItem::CoroutineReturn => lang_items.CoroutineReturn,
+ SolverLangItem::CoroutineYield => lang_items.CoroutineYield,
+ SolverLangItem::FutureOutput => lang_items.FutureOutput,
+ SolverLangItem::Metadata => lang_items.Metadata,
+ SolverLangItem::DynMetadata => {
+ return lang_items.DynMetadata.expect("Lang item required but not found.").into();
+ }
};
- let target = hir_def::lang_item::lang_item(
- self.db(),
- self.krate.expect("Must have self.krate"),
- lang_item,
- )
- .unwrap_or_else(|| panic!("Lang item {lang_item:?} required but not found."));
- match target {
- hir_def::lang_item::LangItemTarget::EnumId(enum_id) => enum_id.into(),
- hir_def::lang_item::LangItemTarget::Function(function_id) => function_id.into(),
- hir_def::lang_item::LangItemTarget::ImplDef(impl_id) => impl_id.into(),
- hir_def::lang_item::LangItemTarget::Static(static_id) => static_id.into(),
- hir_def::lang_item::LangItemTarget::Struct(struct_id) => struct_id.into(),
- hir_def::lang_item::LangItemTarget::Union(union_id) => union_id.into(),
- hir_def::lang_item::LangItemTarget::TypeAlias(type_alias_id) => type_alias_id.into(),
- hir_def::lang_item::LangItemTarget::Trait(trait_id) => trait_id.into(),
- hir_def::lang_item::LangItemTarget::EnumVariant(_) => unimplemented!(),
- }
+ lang_item.expect("Lang item required but not found.").into()
}
fn require_trait_lang_item(self, lang_item: SolverTraitLangItem) -> TraitIdWrapper {
+ let lang_items = self.lang_items();
let lang_item = match lang_item {
- SolverTraitLangItem::AsyncFn => LangItem::AsyncFn,
+ SolverTraitLangItem::AsyncFn => lang_items.AsyncFn,
SolverTraitLangItem::AsyncFnKindHelper => unimplemented!(),
- SolverTraitLangItem::AsyncFnMut => LangItem::AsyncFnMut,
- SolverTraitLangItem::AsyncFnOnce => LangItem::AsyncFnOnce,
- SolverTraitLangItem::AsyncFnOnceOutput => LangItem::AsyncFnOnceOutput,
+ SolverTraitLangItem::AsyncFnMut => lang_items.AsyncFnMut,
+ SolverTraitLangItem::AsyncFnOnce => lang_items.AsyncFnOnce,
+ SolverTraitLangItem::AsyncFnOnceOutput => unimplemented!(
+ "This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver."
+ ),
SolverTraitLangItem::AsyncIterator => unimplemented!(),
- SolverTraitLangItem::Clone => LangItem::Clone,
- SolverTraitLangItem::Copy => LangItem::Copy,
- SolverTraitLangItem::Coroutine => LangItem::Coroutine,
- SolverTraitLangItem::Destruct => LangItem::Destruct,
- SolverTraitLangItem::DiscriminantKind => LangItem::DiscriminantKind,
- SolverTraitLangItem::Drop => LangItem::Drop,
- SolverTraitLangItem::Fn => LangItem::Fn,
- SolverTraitLangItem::FnMut => LangItem::FnMut,
- SolverTraitLangItem::FnOnce => LangItem::FnOnce,
- SolverTraitLangItem::FnPtrTrait => LangItem::FnPtrTrait,
+ SolverTraitLangItem::Clone => lang_items.Clone,
+ SolverTraitLangItem::Copy => lang_items.Copy,
+ SolverTraitLangItem::Coroutine => lang_items.Coroutine,
+ SolverTraitLangItem::Destruct => lang_items.Destruct,
+ SolverTraitLangItem::DiscriminantKind => lang_items.DiscriminantKind,
+ SolverTraitLangItem::Drop => lang_items.Drop,
+ SolverTraitLangItem::Fn => lang_items.Fn,
+ SolverTraitLangItem::FnMut => lang_items.FnMut,
+ SolverTraitLangItem::FnOnce => lang_items.FnOnce,
+ SolverTraitLangItem::FnPtrTrait => lang_items.FnPtrTrait,
SolverTraitLangItem::FusedIterator => unimplemented!(),
- SolverTraitLangItem::Future => LangItem::Future,
- SolverTraitLangItem::Iterator => LangItem::Iterator,
- SolverTraitLangItem::PointeeTrait => LangItem::PointeeTrait,
- SolverTraitLangItem::Sized => LangItem::Sized,
- SolverTraitLangItem::MetaSized => LangItem::MetaSized,
- SolverTraitLangItem::PointeeSized => LangItem::PointeeSized,
- SolverTraitLangItem::TransmuteTrait => LangItem::TransmuteTrait,
- SolverTraitLangItem::Tuple => LangItem::Tuple,
- SolverTraitLangItem::Unpin => LangItem::Unpin,
- SolverTraitLangItem::Unsize => LangItem::Unsize,
+ SolverTraitLangItem::Future => lang_items.Future,
+ SolverTraitLangItem::Iterator => lang_items.Iterator,
+ SolverTraitLangItem::PointeeTrait => lang_items.PointeeTrait,
+ SolverTraitLangItem::Sized => lang_items.Sized,
+ SolverTraitLangItem::MetaSized => lang_items.MetaSized,
+ SolverTraitLangItem::PointeeSized => lang_items.PointeeSized,
+ SolverTraitLangItem::TransmuteTrait => lang_items.TransmuteTrait,
+ SolverTraitLangItem::Tuple => lang_items.Tuple,
+ SolverTraitLangItem::Unpin => lang_items.Unpin,
+ SolverTraitLangItem::Unsize => lang_items.Unsize,
SolverTraitLangItem::BikeshedGuaranteedNoDrop => {
unimplemented!()
}
};
- lang_item
- .resolve_trait(self.db(), self.krate.expect("Must have self.krate"))
- .unwrap_or_else(|| panic!("Lang item {lang_item:?} required but not found."))
- .into()
+ lang_item.expect("Lang item required but not found.").into()
}
fn require_adt_lang_item(self, lang_item: SolverAdtLangItem) -> AdtIdWrapper {
+ let lang_items = self.lang_items();
let lang_item = match lang_item {
- SolverAdtLangItem::Option => LangItem::Option,
- SolverAdtLangItem::Poll => LangItem::Poll,
+ SolverAdtLangItem::Option => lang_items.Option,
+ SolverAdtLangItem::Poll => lang_items.Poll,
};
- lang_item
- .resolve_adt(self.db(), self.krate.expect("Must have self.krate"))
- .unwrap_or_else(|| panic!("Lang item {lang_item:?} required but not found."))
- .into()
+ AdtIdWrapper(lang_item.expect("Lang item required but not found.").into())
}
fn is_lang_item(self, def_id: Self::DefId, lang_item: SolverLangItem) -> bool {
@@ -1520,8 +1546,41 @@ impl<'db> Interner for DbInterner<'db> {
}
fn is_trait_lang_item(self, def_id: Self::TraitId, lang_item: SolverTraitLangItem) -> bool {
- self.as_trait_lang_item(def_id)
- .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item))
+ is_lang_item!(
+ SolverTraitLangItem, self, def_id.0, lang_item;
+
+ ignore = {
+ AsyncFnKindHelper,
+ AsyncIterator,
+ BikeshedGuaranteedNoDrop,
+ FusedIterator,
+ AsyncFnOnceOutput, // This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver.
+ }
+
+ Sized,
+ MetaSized,
+ PointeeSized,
+ Unsize,
+ Copy,
+ Clone,
+ DiscriminantKind,
+ PointeeTrait,
+ FnPtrTrait,
+ Drop,
+ Destruct,
+ TransmuteTrait,
+ Fn,
+ FnMut,
+ FnOnce,
+ Future,
+ Coroutine,
+ Unpin,
+ Tuple,
+ Iterator,
+ AsyncFn,
+ AsyncFnMut,
+ AsyncFnOnce,
+ )
}
fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool {
@@ -1531,42 +1590,57 @@ impl<'db> Interner for DbInterner<'db> {
}
fn as_lang_item(self, def_id: Self::DefId) -> Option<SolverLangItem> {
- let def_id: AttrDefId = match def_id {
- SolverDefId::TraitId(id) => id.into(),
- SolverDefId::TypeAliasId(id) => id.into(),
- SolverDefId::AdtId(id) => id.into(),
- _ => panic!("Unexpected SolverDefId in as_lang_item"),
- };
- let lang_item = self.db().lang_attr(def_id)?;
- as_lang_item!(
- SolverLangItem, lang_item;
+ match def_id {
+ SolverDefId::TypeAliasId(id) => {
+ as_lang_item!(
+ SolverLangItem, self, id;
- ignore = {
- AsyncFnKindUpvars,
+ ignore = {
+ AsyncFnKindUpvars,
+ DynMetadata,
+ }
+
+ Metadata,
+ CoroutineReturn,
+ CoroutineYield,
+ FutureOutput,
+ CallRefFuture,
+ CallOnceFuture,
+ AsyncFnOnceOutput,
+ )
}
+ SolverDefId::AdtId(AdtId::StructId(id)) => {
+ as_lang_item!(
+ SolverLangItem, self, id;
+
+ ignore = {
+ AsyncFnKindUpvars,
+ Metadata,
+ CoroutineReturn,
+ CoroutineYield,
+ FutureOutput,
+ CallRefFuture,
+ CallOnceFuture,
+ AsyncFnOnceOutput,
+ }
- Metadata,
- DynMetadata,
- CoroutineReturn,
- CoroutineYield,
- FutureOutput,
- CallRefFuture,
- CallOnceFuture,
- AsyncFnOnceOutput,
- )
+ DynMetadata,
+ )
+ }
+ _ => panic!("Unexpected SolverDefId in as_lang_item"),
+ }
}
fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem> {
- let def_id: AttrDefId = def_id.0.into();
- let lang_item = self.db().lang_attr(def_id)?;
as_lang_item!(
- SolverTraitLangItem, lang_item;
+ SolverTraitLangItem, self, def_id.0;
ignore = {
AsyncFnKindHelper,
AsyncIterator,
BikeshedGuaranteedNoDrop,
FusedIterator,
+ AsyncFnOnceOutput, // This is incorrectly marked as `SolverTraitLangItem`, and is not used by the solver.
}
Sized,
@@ -1592,15 +1666,15 @@ impl<'db> Interner for DbInterner<'db> {
AsyncFn,
AsyncFnMut,
AsyncFnOnce,
- AsyncFnOnceOutput,
)
}
fn as_adt_lang_item(self, def_id: Self::AdtId) -> Option<SolverAdtLangItem> {
- let def_id: AttrDefId = def_id.0.into();
- let lang_item = self.db().lang_attr(def_id)?;
+ let AdtId::EnumId(def_id) = def_id.0 else {
+ panic!("Unexpected SolverDefId in as_adt_lang_item");
+ };
as_lang_item!(
- SolverAdtLangItem, lang_item;
+ SolverAdtLangItem, self, def_id;
ignore = {}
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index 4f9de5a1a9..c0a7c9adc4 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -5,7 +5,6 @@ use std::ops::ControlFlow;
use hir_def::{
AdtId, HasModule, TypeParamId,
hir::generics::{TypeOrConstParamData, TypeParamProvenance},
- lang_item::LangItem,
};
use hir_def::{TraitId, type_ref::Rawness};
use rustc_abi::{Float, Integer, Size};
@@ -658,7 +657,7 @@ impl<'db> Ty<'db> {
TyKind::Coroutine(coroutine_id, _args) => {
let InternedCoroutine(owner, _) = coroutine_id.0.loc(db);
let krate = owner.module(db).krate();
- if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
+ if let Some(future_trait) = hir_def::lang_item::lang_items(db, krate).Future {
// This is only used by type walking.
// Parameters will be walked outside, and projection predicate is not used.
// So just provide the Future trait.
diff --git a/crates/hir-ty/src/tests/incremental.rs b/crates/hir-ty/src/tests/incremental.rs
index e98e5e4828..62ca2a0592 100644
--- a/crates/hir-ty/src/tests/incremental.rs
+++ b/crates/hir-ty/src/tests/incremental.rs
@@ -44,12 +44,11 @@ fn foo() -> i32 {
"body_shim",
"body_with_source_map_shim",
"trait_environment_shim",
- "GenericPredicates < 'db >::query_with_diagnostics_",
- "lang_item",
+ "lang_items",
"crate_lang_items",
+ "GenericPredicates < 'db >::query_with_diagnostics_",
"ImplTraits < 'db >::return_type_impl_traits_",
"expr_scopes_shim",
- "lang_item",
]
"#]],
);
@@ -133,14 +132,13 @@ fn baz() -> i32 {
"body_shim",
"body_with_source_map_shim",
"trait_environment_shim",
- "GenericPredicates < 'db >::query_with_diagnostics_",
- "lang_item",
+ "lang_items",
"crate_lang_items",
"attrs_shim",
"attrs_shim",
+ "GenericPredicates < 'db >::query_with_diagnostics_",
"ImplTraits < 'db >::return_type_impl_traits_",
"expr_scopes_shim",
- "lang_item",
"infer_shim",
"function_signature_shim",
"function_signature_with_source_map_shim",
@@ -513,10 +511,16 @@ impl SomeStruct {
"impl_trait_with_diagnostics_shim",
"impl_signature_shim",
"impl_signature_with_source_map_shim",
+ "lang_items",
+ "crate_lang_items",
+ "ImplItems::of_",
+ "attrs_shim",
+ "attrs_shim",
+ "attrs_shim",
+ "attrs_shim",
"impl_self_ty_with_diagnostics_shim",
"struct_signature_shim",
"struct_signature_with_source_map_shim",
- "attrs_shim",
]
"#]],
);
@@ -587,12 +591,12 @@ fn main() {
"body_shim",
"body_with_source_map_shim",
"trait_environment_shim",
- "GenericPredicates < 'db >::query_with_diagnostics_",
- "lang_item",
+ "lang_items",
"crate_lang_items",
"attrs_shim",
"attrs_shim",
"GenericPredicates < 'db >::query_with_diagnostics_",
+ "GenericPredicates < 'db >::query_with_diagnostics_",
"ImplTraits < 'db >::return_type_impl_traits_",
"infer_shim",
"function_signature_shim",
@@ -607,7 +611,6 @@ fn main() {
"value_ty_shim",
"VariantFields::firewall_",
"VariantFields::query_",
- "lang_item",
"InherentImpls::for_crate_",
"impl_signature_shim",
"impl_signature_with_source_map_shim",
@@ -617,7 +620,6 @@ fn main() {
"impl_trait_with_diagnostics_shim",
"impl_self_ty_with_diagnostics_shim",
"GenericPredicates < 'db >::query_with_diagnostics_",
- "lang_item",
]
"#]],
);
@@ -684,12 +686,12 @@ fn main() {
"function_signature_shim",
"body_with_source_map_shim",
"body_shim",
- "GenericPredicates < 'db >::query_with_diagnostics_",
"crate_lang_items",
"attrs_shim",
"attrs_shim",
"attrs_shim",
"GenericPredicates < 'db >::query_with_diagnostics_",
+ "GenericPredicates < 'db >::query_with_diagnostics_",
"ImplTraits < 'db >::return_type_impl_traits_",
"infer_shim",
"function_signature_with_source_map_shim",
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 0f5c70ef57..386a95eeb7 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -1,12 +1,11 @@
//! Trait solving using next trait solver.
-use core::fmt;
use std::hash::Hash;
use base_db::Crate;
use hir_def::{
AdtId, AssocItemId, BlockId, HasModule, ImplId, Lookup, TraitId,
- lang_item::LangItem,
+ lang_item::LangItems,
nameres::DefMap,
signatures::{ConstFlags, EnumFlags, FnFlags, StructFlags, TraitFlags, TypeAliasFlags},
};
@@ -165,54 +164,7 @@ pub enum FnTrait {
AsyncFn,
}
-impl fmt::Display for FnTrait {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- FnTrait::FnOnce => write!(f, "FnOnce"),
- FnTrait::FnMut => write!(f, "FnMut"),
- FnTrait::Fn => write!(f, "Fn"),
- FnTrait::AsyncFnOnce => write!(f, "AsyncFnOnce"),
- FnTrait::AsyncFnMut => write!(f, "AsyncFnMut"),
- FnTrait::AsyncFn => write!(f, "AsyncFn"),
- }
- }
-}
-
impl FnTrait {
- pub const fn function_name(&self) -> &'static str {
- match self {
- FnTrait::FnOnce => "call_once",
- FnTrait::FnMut => "call_mut",
- FnTrait::Fn => "call",
- FnTrait::AsyncFnOnce => "async_call_once",
- FnTrait::AsyncFnMut => "async_call_mut",
- FnTrait::AsyncFn => "async_call",
- }
- }
-
- const fn lang_item(self) -> LangItem {
- match self {
- FnTrait::FnOnce => LangItem::FnOnce,
- FnTrait::FnMut => LangItem::FnMut,
- FnTrait::Fn => LangItem::Fn,
- FnTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
- FnTrait::AsyncFnMut => LangItem::AsyncFnMut,
- FnTrait::AsyncFn => LangItem::AsyncFn,
- }
- }
-
- pub const fn from_lang_item(lang_item: LangItem) -> Option<Self> {
- match lang_item {
- LangItem::FnOnce => Some(FnTrait::FnOnce),
- LangItem::FnMut => Some(FnTrait::FnMut),
- LangItem::Fn => Some(FnTrait::Fn),
- LangItem::AsyncFnOnce => Some(FnTrait::AsyncFnOnce),
- LangItem::AsyncFnMut => Some(FnTrait::AsyncFnMut),
- LangItem::AsyncFn => Some(FnTrait::AsyncFn),
- _ => None,
- }
- }
-
pub fn method_name(self) -> Name {
match self {
FnTrait::FnOnce => Name::new_symbol_root(sym::call_once),
@@ -224,8 +176,15 @@ impl FnTrait {
}
}
- pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<TraitId> {
- self.lang_item().resolve_trait(db, krate)
+ pub fn get_id(self, lang_items: &LangItems) -> Option<TraitId> {
+ match self {
+ FnTrait::FnOnce => lang_items.FnOnce,
+ FnTrait::FnMut => lang_items.FnMut,
+ FnTrait::Fn => lang_items.Fn,
+ FnTrait::AsyncFnOnce => lang_items.AsyncFnOnce,
+ FnTrait::AsyncFnMut => lang_items.AsyncFnMut,
+ FnTrait::AsyncFn => lang_items.AsyncFn,
+ }
}
}
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index ca5e33fe6a..820ccd9908 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -3,15 +3,12 @@
use std::cell::LazyCell;
-use base_db::{
- Crate,
- target::{self, TargetData},
-};
+use base_db::target::{self, TargetData};
use hir_def::{
EnumId, EnumVariantId, FunctionId, Lookup, TraitId,
db::DefDatabase,
hir::generics::WherePredicate,
- lang_item::LangItem,
+ lang_item::LangItems,
resolver::{HasResolver, TypeNs},
type_ref::{TraitBoundModifier, TypeRef},
};
@@ -27,10 +24,8 @@ use crate::{
mir::pad16,
};
-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| lang.resolve_trait(db, krate))
+pub(crate) fn fn_traits(lang_items: &LangItems) -> impl Iterator<Item = TraitId> + '_ {
+ [lang_items.Fn, lang_items.FnMut, lang_items.FnOnce].into_iter().flatten()
}
/// Returns an iterator over the direct super traits (including the trait itself).
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index c215438aad..10a1fa12e0 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -6,7 +6,6 @@ use hir_def::{
expr_store::ExpressionStore,
hir::generics::{GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate},
item_tree::FieldsShape,
- lang_item::LangItem,
signatures::{StaticFlags, TraitFlags},
type_ref::{TypeBound, TypeRef, TypeRefId},
};
@@ -520,7 +519,7 @@ impl<'db> HirDisplay<'db> for TypeParam {
return Ok(());
}
- let sized_trait = LangItem::Sized.resolve_trait(f.db, krate);
+ let sized_trait = f.lang_items().Sized;
let has_only_sized_bound =
predicates.iter().all(move |pred| match pred.kind().skip_binder() {
ClauseKind::Trait(it) => Some(it.def_id().0) == sized_trait,
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index f941cbd232..4c21b98066 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -59,6 +59,7 @@ use hir_def::{
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
},
item_tree::ImportAlias,
+ lang_item::LangItemTarget,
layout::{self, ReprOptions, TargetDataLayout},
nameres::{
assoc::TraitItems,
@@ -91,7 +92,7 @@ use hir_ty::{
PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode,
infer::{DbInternerInferExt, InferCtxt},
},
- traits::{self, FnTrait, is_inherent_impl_coherent, structurally_normalize_ty},
+ traits::{self, is_inherent_impl_coherent, structurally_normalize_ty},
};
use itertools::Itertools;
use rustc_hash::FxHashSet;
@@ -138,7 +139,7 @@ pub use {
attr::{AttrSourceMap, Attrs, AttrsWithOwner},
find_path::PrefixKind,
import_map,
- lang_item::{LangItem, crate_lang_items},
+ lang_item::{LangItemEnum as LangItem, crate_lang_items},
nameres::{DefMap, ModuleSource, crate_def_map},
per_ns::Namespace,
type_ref::{Mutability, TypeRef},
@@ -818,7 +819,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 = LangItem::Drop.resolve_trait(db, self.krate().into())?;
+ let drop_trait = interner.lang_items().Drop?;
if drop_trait != trait_.into() {
return None;
}
@@ -2436,11 +2437,11 @@ impl Function {
let ret_type = self.ret_type(db);
let Some(impl_traits) = ret_type.as_impl_traits(db) else { return false };
- let Some(future_trait_id) = LangItem::Future.resolve_trait(db, self.ty(db).env.krate)
- else {
+ let lang_items = hir_def::lang_item::lang_items(db, self.krate(db).id);
+ let Some(future_trait_id) = lang_items.Future else {
return false;
};
- let Some(sized_trait_id) = LangItem::Sized.resolve_trait(db, self.ty(db).env.krate) else {
+ let Some(sized_trait_id) = lang_items.Sized else {
return false;
};
@@ -2905,8 +2906,12 @@ pub struct Trait {
}
impl Trait {
- pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
- LangItem::from_name(name)?.resolve_trait(db, krate.into()).map(Into::into)
+ pub fn lang(db: &dyn HirDatabase, krate: Crate, lang_item: LangItem) -> Option<Trait> {
+ let lang_items = hir_def::lang_item::lang_items(db, krate.id);
+ match lang_item.from_lang_items(lang_items)? {
+ LangItemTarget::TraitId(it) => Some(it.into()),
+ _ => None,
+ }
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -4650,7 +4655,7 @@ impl<'db> Closure<'db> {
let owner = db.lookup_intern_closure(id).0;
let infer = db.infer(owner);
let info = infer.closure_info(id);
- info.1
+ info.1.into()
}
AnyClosureId::CoroutineClosureId(_id) => {
// FIXME: Infer kind for coroutine closures.
@@ -4664,6 +4669,71 @@ impl<'db> Closure<'db> {
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum FnTrait {
+ FnOnce,
+ FnMut,
+ Fn,
+
+ AsyncFnOnce,
+ AsyncFnMut,
+ AsyncFn,
+}
+
+impl From<traits::FnTrait> for FnTrait {
+ fn from(value: traits::FnTrait) -> Self {
+ match value {
+ traits::FnTrait::FnOnce => FnTrait::FnOnce,
+ traits::FnTrait::FnMut => FnTrait::FnMut,
+ traits::FnTrait::Fn => FnTrait::Fn,
+ traits::FnTrait::AsyncFnOnce => FnTrait::AsyncFnOnce,
+ traits::FnTrait::AsyncFnMut => FnTrait::AsyncFnMut,
+ traits::FnTrait::AsyncFn => FnTrait::AsyncFn,
+ }
+ }
+}
+
+impl fmt::Display for FnTrait {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ FnTrait::FnOnce => write!(f, "FnOnce"),
+ FnTrait::FnMut => write!(f, "FnMut"),
+ FnTrait::Fn => write!(f, "Fn"),
+ FnTrait::AsyncFnOnce => write!(f, "AsyncFnOnce"),
+ FnTrait::AsyncFnMut => write!(f, "AsyncFnMut"),
+ FnTrait::AsyncFn => write!(f, "AsyncFn"),
+ }
+ }
+}
+
+impl FnTrait {
+ pub const fn function_name(&self) -> &'static str {
+ match self {
+ FnTrait::FnOnce => "call_once",
+ FnTrait::FnMut => "call_mut",
+ FnTrait::Fn => "call",
+ FnTrait::AsyncFnOnce => "async_call_once",
+ FnTrait::AsyncFnMut => "async_call_mut",
+ FnTrait::AsyncFn => "async_call",
+ }
+ }
+
+ pub fn lang_item(self) -> LangItem {
+ match self {
+ FnTrait::FnOnce => LangItem::FnOnce,
+ FnTrait::FnMut => LangItem::FnMut,
+ FnTrait::Fn => LangItem::Fn,
+ FnTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
+ FnTrait::AsyncFnMut => LangItem::AsyncFnMut,
+ FnTrait::AsyncFn => LangItem::AsyncFn,
+ }
+ }
+
+ pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<Trait> {
+ Trait::lang(db, krate, self.lang_item())
+ }
+}
+
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClosureCapture<'db> {
owner: DefWithBodyId,
@@ -5052,14 +5122,15 @@ impl<'db> Type<'db> {
/// `std::future::Future` and returns the `Output` associated type.
/// This function is used in `.await` syntax completion.
pub fn into_future_output(&self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let trait_ = LangItem::IntoFutureIntoFuture
- .resolve_function(db, self.env.krate)
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let trait_ = lang_items
+ .IntoFutureIntoFuture
.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(|| LangItem::Future.resolve_trait(db, self.env.krate))?;
+ .or(lang_items.Future)?;
if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
return None;
@@ -5072,13 +5143,15 @@ impl<'db> Type<'db> {
/// This does **not** resolve `IntoFuture`, only `Future`.
pub fn future_output(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let future_output = LangItem::FutureOutput.resolve_type_alias(db, self.env.krate)?;
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let future_output = lang_items.FutureOutput?;
self.normalize_trait_assoc_type(db, &[], future_output.into())
}
/// This does **not** resolve `IntoIterator`, only `Iterator`.
pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let iterator_trait = lang_items.Iterator?;
let iterator_item = iterator_trait
.trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
@@ -5086,7 +5159,8 @@ impl<'db> Type<'db> {
}
pub fn impls_iterator(self, db: &'db dyn HirDatabase) -> bool {
- let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else {
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let Some(iterator_trait) = lang_items.Iterator else {
return false;
};
traits::implements_trait_unique(self.ty, db, self.env.clone(), iterator_trait)
@@ -5094,13 +5168,12 @@ impl<'db> Type<'db> {
/// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- 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 lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let trait_ = lang_items.IntoIterIntoIter.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)
+ })?;
if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
return None;
@@ -5117,7 +5190,8 @@ impl<'db> Type<'db> {
/// This function can be used to check if a particular type is callable, since FnOnce is a
/// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
pub fn impls_fnonce(&self, db: &'db dyn HirDatabase) -> bool {
- let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) {
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let fnonce_trait = match lang_items.FnOnce {
Some(it) => it,
None => return false,
};
@@ -5161,7 +5235,8 @@ impl<'db> Type<'db> {
}
pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool {
- let Some(copy_trait) = LangItem::Copy.resolve_trait(db, self.env.krate) else {
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let Some(copy_trait) = lang_items.Copy else {
return false;
};
self.impls_trait(db, copy_trait.into(), &[])
@@ -5913,7 +5988,7 @@ enum Callee<'db> {
Closure(InternedClosureId, GenericArgs<'db>),
CoroutineClosure(InternedCoroutineId, GenericArgs<'db>),
FnPtr,
- FnImpl(FnTrait),
+ FnImpl(traits::FnTrait),
}
pub enum CallableKind<'db> {
@@ -5940,7 +6015,7 @@ impl<'db> Callable<'db> {
CallableKind::Closure(Closure { id: AnyClosureId::CoroutineClosureId(id), subst })
}
Callee::FnPtr => CallableKind::FnPtr,
- Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_),
+ Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_.into()),
}
}
pub fn receiver_param(&self, db: &'db dyn HirDatabase) -> Option<(SelfParam, Type<'db>)> {
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index b4389797e6..f29e4ccf60 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -18,7 +18,7 @@ use hir_def::{
scope::{ExprScopes, ScopeId},
},
hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat},
- lang_item::LangItem,
+ lang_item::LangItems,
nameres::MacroSubNs,
resolver::{HasResolver, Resolver, TypeNs, ValueNs, resolver_for_scope},
type_ref::{Mutability, TypeRef, TypeRefId},
@@ -589,7 +589,7 @@ impl<'db> SourceAnalyzer<'db> {
}
}
- let poll_fn = LangItem::FuturePoll.resolve_function(db, self.resolver.krate())?;
+ let poll_fn = self.lang_items(db).FuturePoll?;
// 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 interner = DbInterner::new_no_crate(db);
@@ -607,15 +607,18 @@ impl<'db> SourceAnalyzer<'db> {
// This can be either `Deref::deref` or `DerefMut::deref_mut`.
// Since deref kind is inferenced and stored in `InferenceResult.method_resolution`,
// use that result to find out which one it is.
- let (deref_trait, deref) =
- self.lang_trait_fn(db, LangItem::Deref, &Name::new_symbol_root(sym::deref))?;
+ let (deref_trait, deref) = self.lang_trait_fn(
+ db,
+ self.lang_items(db).Deref,
+ &Name::new_symbol_root(sym::deref),
+ )?;
self.infer()
.and_then(|infer| {
let expr = self.expr_id(prefix_expr.clone().into())?.as_expr()?;
let (func, _) = infer.method_resolution(expr)?;
let (deref_mut_trait, deref_mut) = self.lang_trait_fn(
db,
- LangItem::DerefMut,
+ self.lang_items(db).DerefMut,
&Name::new_symbol_root(sym::deref_mut),
)?;
if func == deref_mut { Some((deref_mut_trait, deref_mut)) } else { None }
@@ -623,10 +626,10 @@ impl<'db> SourceAnalyzer<'db> {
.unwrap_or((deref_trait, deref))
}
ast::UnaryOp::Not => {
- self.lang_trait_fn(db, LangItem::Not, &Name::new_symbol_root(sym::not))?
+ self.lang_trait_fn(db, self.lang_items(db).Not, &Name::new_symbol_root(sym::not))?
}
ast::UnaryOp::Neg => {
- self.lang_trait_fn(db, LangItem::Neg, &Name::new_symbol_root(sym::neg))?
+ self.lang_trait_fn(db, self.lang_items(db).Neg, &Name::new_symbol_root(sym::neg))?
}
};
@@ -649,7 +652,7 @@ impl<'db> SourceAnalyzer<'db> {
let index_ty = self.ty_of_expr(index_expr.index()?)?;
let (_index_trait, index_fn) =
- self.lang_trait_fn(db, LangItem::Index, &Name::new_symbol_root(sym::index))?;
+ self.lang_trait_fn(db, self.lang_items(db).Index, &Name::new_symbol_root(sym::index))?;
let op_fn = self
.infer()
.and_then(|infer| {
@@ -657,7 +660,7 @@ impl<'db> SourceAnalyzer<'db> {
let (func, _) = infer.method_resolution(expr)?;
let (_index_mut_trait, index_mut_fn) = self.lang_trait_fn(
db,
- LangItem::IndexMut,
+ self.lang_items(db).IndexMut,
&Name::new_symbol_root(sym::index_mut),
)?;
if func == index_mut_fn { Some(index_mut_fn) } else { None }
@@ -679,9 +682,10 @@ impl<'db> SourceAnalyzer<'db> {
let lhs = self.ty_of_expr(binop_expr.lhs()?)?;
let rhs = self.ty_of_expr(binop_expr.rhs()?)?;
- let (_op_trait, op_fn) = lang_items_for_bin_op(op).and_then(|(name, lang_item)| {
- self.lang_trait_fn(db, lang_item, &Name::new_symbol_root(name))
- })?;
+ let (_op_trait, op_fn) =
+ lang_items_for_bin_op(self.lang_items(db), op).and_then(|(name, lang_item)| {
+ self.lang_trait_fn(db, lang_item, &Name::new_symbol_root(name))
+ })?;
// HACK: subst for `index()` coincides with that for `Index` because `index()` itself
// doesn't have any generic parameters, so we skip building another subst for `index()`.
let interner = DbInterner::new_no_crate(db);
@@ -697,7 +701,7 @@ impl<'db> SourceAnalyzer<'db> {
) -> Option<FunctionId> {
let ty = self.ty_of_expr(try_expr.expr()?)?;
- let op_fn = LangItem::TryTraitBranch.resolve_function(db, self.resolver.krate())?;
+ let op_fn = self.lang_items(db).TryTraitBranch?;
// HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself
// doesn't have any generic parameters, so we skip building another subst for `branch()`.
let interner = DbInterner::new_no_crate(db);
@@ -1428,13 +1432,17 @@ impl<'db> SourceAnalyzer<'db> {
method_resolution::lookup_impl_const(&infcx, env, const_id, subs)
}
+ fn lang_items<'a>(&self, db: &'a dyn HirDatabase) -> &'a LangItems {
+ hir_def::lang_item::lang_items(db, self.resolver.krate())
+ }
+
fn lang_trait_fn(
&self,
db: &'db dyn HirDatabase,
- lang_trait: LangItem,
+ lang_trait: Option<TraitId>,
method_name: &Name,
) -> Option<(TraitId, FunctionId)> {
- let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?;
+ let trait_id = lang_trait?;
let fn_id = trait_id.trait_items(db).method_by_name(method_name)?;
Some((trait_id, fn_id))
}
diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs
index e139a5e270..155f0b5a98 100644
--- a/crates/ide-completion/src/tests/flyimport.rs
+++ b/crates/ide-completion/src/tests/flyimport.rs
@@ -780,9 +780,9 @@ fn main() {
}
"#,
expect![[r#"
+ me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
ct SPECIAL_CONST (use dep::test_mod::TestTrait) u8 DEPRECATED
fn weird_function() (use dep::test_mod::TestTrait) fn() DEPRECATED
- me random_method(…) (use dep::test_mod::TestTrait) fn(&self) DEPRECATED
"#]],
);
}
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index fa4b4b6d24..dae2136f25 100644
--- a/crates/ide/src/hover.rs
+++ b/crates/ide/src/hover.rs
@@ -6,9 +6,7 @@ mod tests;
use std::{iter, ops::Not};
use either::Either;
-use hir::{
- DisplayTarget, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics,
-};
+use hir::{DisplayTarget, GenericDef, GenericSubstitution, HasCrate, HasSource, Semantics};
use ide_db::{
FileRange, FxIndexSet, MiniCore, Ranker, RootDatabase,
defs::{Definition, IdentClass, NameRefClass, OperatorClass},
@@ -675,10 +673,10 @@ 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 = LangItem::Sized.resolve_trait(db, t.krate(db).into());
+ let sized_trait = hir::Trait::lang(db, t.krate(db), hir::LangItem::Sized);
tp.trait_bounds(db)
.into_iter()
- .filter(|&it| Some(it.into()) != sized_trait)
+ .filter(|&it| Some(it) != sized_trait)
.for_each(|it| push_new_def(it.into()));
}
});
diff --git a/crates/ide/src/hover/render.rs b/crates/ide/src/hover/render.rs
index a1eff3aaee..8c2d3f0e5f 100644
--- a/crates/ide/src/hover/render.rs
+++ b/crates/ide/src/hover/render.rs
@@ -1083,8 +1083,8 @@ fn closure_ty(
};
let mut markup = format!("```rust\n{}\n```", c.display_with_impl(sema.db, display_target));
- if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db).into()) {
- push_new_def(hir::Trait::from(trait_).into())
+ if let Some(trait_) = c.fn_trait(sema.db).get_id(sema.db, original.krate(sema.db)) {
+ push_new_def(trait_.into())
}
if let Some(layout) = render_memory_layout(
config.memory_layout,