diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index b4fcfa11aea7..6d3005e01cb1 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/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 { - 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/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs index 49aafb2b86a3..d6bba6306bc4 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs +++ b/src/tools/rust-analyzer/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; - // endregion:attrs #[salsa::invoke(ImportMap::import_map_query)] diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs index e3bfc5b753ae..238538dc58d8 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/lower.rs +++ b/src/tools/rust-analyzer/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, @@ -539,6 +541,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 { ; }` into `': { ; ::std::ops::Try::from_output(()) }` /// and save the `` 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, 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, 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, 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 { - lang.path(self.db, self.module.krate()) + fn lang_path(&self, lang: Option>) -> Option { + Some(Path::LangItem(lang?.into(), None)) + } + + fn ty_rel_lang_path( + &self, + lang: Option>, + relative_name: Name, + ) -> Option { + Some(Path::LangItem(lang?.into(), Some(relative_name))) } } diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs index 4ba70938d08c..42d3e07d9c94 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs index 91a90f6d84b4..e634a95b6762 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/lang_item.rs @@ -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 { - match self { - LangItemTarget::EnumId(id) => Some(id), - _ => None, - } - } - - pub fn as_function(self) -> Option { - match self { - LangItemTarget::Function(id) => Some(id), - _ => None, - } - } - - pub fn as_impl_def(self) -> Option { - match self { - LangItemTarget::ImplDef(id) => Some(id), - _ => None, - } - } - - pub fn as_static(self) -> Option { - match self { - LangItemTarget::Static(id) => Some(id), - _ => None, - } - } - - pub fn as_struct(self) -> Option { - match self { - LangItemTarget::Struct(id) => Some(id), - _ => None, - } - } - - pub fn as_trait(self) -> Option { - match self { - LangItemTarget::Trait(id) => Some(id), - _ => None, - } - } - - pub fn as_enum_variant(self) -> Option { - match self { - LangItemTarget::EnumVariant(id) => Some(id), - _ => None, - } - } - - pub fn as_type_alias(self) -> Option { - match self { - LangItemTarget::TypeAlias(id) => Some(id), - _ => None, - } - } - - pub fn as_adt(self) -> Option { - 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> { +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 { - 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 { - 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 { - 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, + result } impl LangItems { - pub fn target(&self, item: LangItem) -> Option { - self.items.get(&item).copied() - } - - fn collect_lang_item( - &mut self, - db: &dyn DefDatabase, - item: T, - constructor: fn(T) -> LangItemTarget, - ) where - T: Into + Copy, + fn collect_lang_item(&mut self, db: &dyn DefDatabase, item: T) + where + T: Into + Into + 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 { - db.attrs(item).lang_item() -} - #[salsa::tracked(returns(as_deref))] pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option> { 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 { - 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 { - lang_item(db, start_crate, self).and_then(|t| t.as_function()) - } + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + pub enum LangItemEnum { + $( + $(#[$attr])* + $lang_item, + )* + } - pub fn resolve_trait(self, db: &dyn DefDatabase, start_crate: Crate) -> Option { - lang_item(db, start_crate, self).and_then(|t| t.as_trait()) - } - - pub fn resolve_adt(self, db: &dyn DefDatabase, start_crate: Crate) -> Option { - lang_item(db, start_crate, self).and_then(|t| t.as_adt()) - } - - pub fn resolve_enum(self, db: &dyn DefDatabase, start_crate: Crate) -> Option { - 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 { - 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::from_symbol(name.symbol()) - } - - pub fn path(&self, db: &dyn DefDatabase, start_crate: Crate) -> Option { - let t = lang_item(db, start_crate, *self)?; - Some(Path::LangItem(t, None)) - } - - pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option { - 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 { + 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); + 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, 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); + 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, 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; + 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, 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; + 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, 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); + 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, 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; + 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, Target::AssocTy, GenericRequirement::None; + FnOnceOutput, sym::fn_once_output, fn_once_output, TypeAliasId, 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; + 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, 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; + 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/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs index b5afbf387dfc..ccea043739c2 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs b/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs index ebbf87cad668..405bb445594c 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/signatures.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs b/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs index d21108fb5ab3..4efe64377b7a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/autoderef.rs +++ b/src/tools/rust-analyzer/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; @@ -38,7 +38,7 @@ pub fn autoderef<'db>( env: Arc>, ty: Canonical<'db, Ty<'db>>, ) -> impl Iterator> + use<'db> { - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, env.krate, env.block); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let (ty, _) = infcx.instantiate_canonical(&ty); let autoderef = Autoderef::new(&infcx, &env, ty); @@ -301,36 +301,28 @@ where self.infcx().interner } - #[inline] - fn db(&self) -> &'db dyn HirDatabase { - self.interner().db - } - fn autoderef_traits(&mut self) -> Option { + 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/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs index 61f29b4ab747..8430c3a41cde 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs @@ -83,7 +83,7 @@ pub fn intern_const_ref<'a>( ty: Ty<'a>, krate: Crate, ) -> Const<'a> { - let interner = DbInterner::new_with(db, Some(krate), None); + let interner = DbInterner::new_no_crate(db); let layout = db.layout_of_ty(ty, TraitEnvironment::empty(krate)); let kind = match value { LiteralConstRef::Int(i) => { @@ -128,7 +128,7 @@ pub fn usize_const<'db>(db: &'db dyn HirDatabase, value: Option, krate: Cr intern_const_ref( db, &value.map_or(LiteralConstRef::Unknown, LiteralConstRef::UInt), - Ty::new_uint(DbInterner::new_with(db, Some(krate), None), rustc_type_ir::UintTy::Usize), + Ty::new_uint(DbInterner::new_no_crate(db), rustc_type_ir::UintTy::Usize), krate, ) } @@ -183,7 +183,7 @@ pub(crate) fn const_eval_discriminant_variant<'db>( db: &'db dyn HirDatabase, variant_id: EnumVariantId, ) -> Result> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let def = variant_id.into(); let body = db.body(def); let loc = variant_id.lookup(db); @@ -292,7 +292,7 @@ pub(crate) fn const_eval_static_query<'db>( db: &'db dyn HirDatabase, def: StaticId, ) -> Result, ConstEvalError<'db>> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let body = db.monomorphized_mir_body( def.into(), GenericArgs::new_from_iter(interner, []), diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs index 609525071357..f25147622f06 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs @@ -123,7 +123,7 @@ fn pretty_print_err(e: ConstEvalError<'_>, db: &TestDB) -> String { fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result, ConstEvalError<'_>> { let _tracing = setup_tracing(); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let module_id = db.module_for_file(file_id.file_id(db)); let def_map = module_id.def_map(db); let scope = &def_map[module_id.local_id].scope; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs index 0eca0c09d690..b84b70c197d0 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs @@ -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; @@ -79,7 +79,7 @@ impl BodyValidationDiagnostic { let infer = db.infer(owner); let body = db.body(owner); let env = db.trait_environment_for_body(owner); - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, env.krate, env.block); let infcx = interner.infer_ctxt().build(TypingMode::typeck_for_body(interner, owner.into())); let mut validator = ExprValidator { @@ -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/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs index 6767bd05b336..2c6d7c68d1d3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs +++ b/src/tools/rust-analyzer/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 { @@ -309,8 +309,7 @@ pub trait HirDisplay<'db> { allow_opaque: bool, ) -> Result { let mut result = String::new(); - let interner = - DbInterner::new_with(db, Some(module_id.krate()), module_id.containing_block()); + let interner = DbInterner::new_with(db, module_id.krate(), module_id.containing_block()); match self.hir_fmt(&mut HirFormatter { db, interner, @@ -392,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>( &mut self, iter: impl IntoIterator, @@ -544,7 +548,7 @@ impl<'db, T: HirDisplay<'db>> HirDisplayWrapper<'_, 'db, T> { DisplayKind::SourceCode { target_module_id, .. } => target_module_id.containing_block(), DisplayKind::Diagnostics | DisplayKind::Test => None, }; - let interner = DbInterner::new_with(self.db, Some(krate), block); + let interner = DbInterner::new_with(self.db, krate, block); self.t.hir_fmt(&mut HirFormatter { db: self.db, interner, @@ -1102,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, }); @@ -1146,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 } @@ -1588,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)) @@ -1799,11 +1802,6 @@ impl<'db> HirDisplay<'db> for Term<'db> { } } -fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator + '_ { - let krate = trait_.lookup(db).container.krate(); - utils::fn_traits(db, krate) -} - #[derive(Clone, Copy, PartialEq, Eq)] pub enum SizedByDefault { NotSized, @@ -1815,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 } } @@ -1868,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, ">")?; @@ -1966,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/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs b/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs index aebb6def93d9..124e7b279f13 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/drop.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs index 1bd5981d10e2..a658302b0989 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/dyn_compatibility.rs @@ -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::{ @@ -53,7 +53,7 @@ pub fn dyn_compatibility( db: &dyn HirDatabase, trait_: TraitId, ) -> Option { - let interner = DbInterner::new_with(db, Some(trait_.krate(db)), None); + let interner = DbInterner::new_no_crate(db); for super_trait in elaborate::supertrait_def_ids(interner, trait_.into()) { if let Some(v) = db.dyn_compatibility_of_trait(super_trait.0) { return if super_trait.0 == trait_ { @@ -75,7 +75,7 @@ pub fn dyn_compatibility_with_callback( where F: FnMut(DynCompatibilityViolation) -> ControlFlow<()>, { - let interner = DbInterner::new_with(db, Some(trait_.krate(db)), None); + let interner = DbInterner::new_no_crate(db); for super_trait in elaborate::supertrait_def_ids(interner, trait_.into()).skip(1) { if db.dyn_compatibility_of_trait(super_trait.0).is_some() { cb(DynCompatibilityViolation::HasNonCompatibleSuperTrait(trait_))?; @@ -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_with(db, Some(krate), None); let predicates = GenericPredicates::query_explicit(db, def); // FIXME: We should use `explicit_predicates_of` here, which hasn't been implemented to // rust-analyzer yet @@ -234,34 +234,34 @@ fn contains_illegal_self_type_reference<'db, T: rustc_type_ir::TypeVisitable as rustc_type_ir::Interner>::Ty, ) -> Self::Result { - let interner = DbInterner::new_with(self.db, None, None); + let interner = DbInterner::new_no_crate(self.db); match ty.kind() { rustc_type_ir::TyKind::Param(param) if param.index == 0 => ControlFlow::Break(()), rustc_type_ir::TyKind::Param(_) => ControlFlow::Continue(()), - rustc_type_ir::TyKind::Alias(AliasTyKind::Projection, proj) => match self - .allow_self_projection - { - AllowSelfProjection::Yes => { - let trait_ = proj.trait_def_id(DbInterner::new_with(self.db, None, None)); - let trait_ = match trait_ { - SolverDefId::TraitId(id) => id, - _ => unreachable!(), - }; - if self.super_traits.is_none() { - self.super_traits = Some( - elaborate::supertrait_def_ids(interner, self.trait_.into()) - .map(|super_trait| super_trait.0) - .collect(), - ) - } - if self.super_traits.as_ref().is_some_and(|s| s.contains(&trait_)) { - ControlFlow::Continue(()) - } else { - ty.super_visit_with(self) + rustc_type_ir::TyKind::Alias(AliasTyKind::Projection, proj) => { + match self.allow_self_projection { + AllowSelfProjection::Yes => { + let trait_ = proj.trait_def_id(interner); + let trait_ = match trait_ { + SolverDefId::TraitId(id) => id, + _ => unreachable!(), + }; + if self.super_traits.is_none() { + self.super_traits = Some( + elaborate::supertrait_def_ids(interner, self.trait_.into()) + .map(|super_trait| super_trait.0) + .collect(), + ) + } + if self.super_traits.as_ref().is_some_and(|s| s.contains(&trait_)) { + ControlFlow::Continue(()) + } else { + ty.super_visit_with(self) + } } + AllowSelfProjection::No => ty.super_visit_with(self), } - AllowSelfProjection::No => ty.super_visit_with(self), - }, + } _ => ty.super_visit_with(self), } } @@ -401,7 +401,8 @@ fn receiver_is_dispatchable<'db>( ) -> bool { let sig = sig.instantiate_identity(); - let interner: DbInterner<'_> = DbInterner::new_with(db, Some(trait_.krate(db)), None); + let module = trait_.module(db); + let interner = DbInterner::new_with(db, module.krate(), module.containing_block()); let self_param_id = TypeParamId::from_unchecked(TypeOrConstParamId { parent: trait_.into(), local_id: LocalTypeOrConstParamId::from_raw(la_arena::RawIdx::from_u32(0)), @@ -419,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/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs index 1d9f7dc06514..411e8b8dc705 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs +++ b/src/tools/rust-analyzer/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}, @@ -168,7 +168,7 @@ pub(crate) fn infer_cycle_result( ) -> Arc> { Arc::new(InferenceResult { has_errors: true, - ..InferenceResult::new(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)) + ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed)) }) } @@ -834,6 +834,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, pub(crate) result: InferenceResult<'db>, @@ -939,6 +940,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(), @@ -1854,21 +1856,13 @@ impl<'body, 'db> InferenceContext<'body, 'db> { } } - fn resolve_lang_item(&self, item: LangItem) -> Option { - let krate = self.resolver.krate(); - lang_item(self.db, krate, item) - } - fn resolve_output_on(&self, trait_: TraitId) -> Option { trait_.trait_items(self.db).associated_type_by_name(&Name::new_symbol_root(sym::Output)) } fn resolve_future_future_output(&self) -> Option { - 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; }; @@ -1876,42 +1870,42 @@ impl<'body, 'db> InferenceContext<'body, 'db> { } fn resolve_boxed_box(&self) -> Option { - 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 { - let struct_ = self.resolve_lang_item(LangItem::RangeFull)?.as_struct()?; + let struct_ = self.lang_items.RangeFull?; Some(struct_.into()) } fn resolve_range(&self) -> Option { - 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 { - 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 { - 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 { - 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 { - 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 { - let struct_ = self.resolve_lang_item(LangItem::VaList)?.as_struct()?; + let struct_ = self.lang_items.VaList?; Some(struct_.into()) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs index 54a06ebd2ce0..89ebd2b21d09 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs +++ b/src/tools/rust-analyzer/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 { - 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 { - 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> { 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` 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/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis.rs index 944b3594bac7..935c5a507849 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure/analysis.rs @@ -101,7 +101,7 @@ impl<'db> CapturedItem<'db> { } pub fn ty(&self, db: &'db dyn HirDatabase, subst: GenericArgs<'db>) -> Ty<'db> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); self.ty.instantiate(interner, subst.split_closure_args_untupled().parent_args) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs index add8fc9bfcac..773a02c5f60c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/coerce.rs @@ -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); @@ -1578,7 +1575,7 @@ fn coerce<'db>( env: Arc>, tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, ) -> Result<(Vec>, Ty<'db>), TypeError>> { - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, env.krate, env.block); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let ((ty1_with_vars, ty2_with_vars), vars) = infcx.instantiate_canonical(tys); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs index d3d6d1ed61d1..200b3d71f8be 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs +++ b/src/tools/rust-analyzer/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}; @@ -877,14 +876,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, @@ -1283,7 +1278,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/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs index a257547e09c2..87dcaa8a4ea8 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/mutability.rs @@ -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/src/tools/rust-analyzer/crates/hir-ty/src/infer/op.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/op.rs index 88319a8b1ad4..6fbac8f5aeb5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/op.rs +++ b/src/tools/rust-analyzer/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) { 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) { 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/src/tools/rust-analyzer/crates/hir-ty/src/infer/place_op.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/place_op.rs index 50018bb23bf3..9544fb449f55 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/place_op.rs +++ b/src/tools/rust-analyzer/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>, op: PlaceOp, ) -> Option>> { 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/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs index 0b566497c4b6..f25ed3f2e6a5 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs @@ -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; @@ -113,7 +113,7 @@ fn could_unify_impl<'db>( tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>, select: for<'a> fn(&mut ObligationCtxt<'a, 'db>) -> Vec>, ) -> bool { - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, env.krate, env.block); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let cause = ObligationCause::dummy(); let at = infcx.at(&cause, env.env); @@ -148,7 +148,7 @@ impl<'db> InferenceTable<'db> { trait_env: Arc>, owner: Option, ) -> Self { - let interner = DbInterner::new_with(db, Some(trait_env.krate), trait_env.block); + let interner = DbInterner::new_with(db, trait_env.krate, trait_env.block); let typing_mode = match owner { Some(owner) => TypingMode::typeck_for_body(interner, owner.into()), // IDE things wants to reveal opaque types. @@ -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>)> { + 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/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs index d0d0aa7a9039..18feb0f46a32 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lang_items.rs +++ b/src/tools/rust-analyzer/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)> { 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/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index fc0b9d30b333..908b4dc5d70d 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -143,7 +143,7 @@ fn layout_of_simd_ty<'db>( let Some(TyKind::Array(e_ty, e_len)) = fields .next() .filter(|_| fields.next().is_none()) - .map(|f| (*f.1).instantiate(DbInterner::new_with(db, None, None), args).kind()) + .map(|f| (*f.1).instantiate(DbInterner::new_no_crate(db), args).kind()) else { return Err(LayoutError::InvalidSimdType); }; @@ -161,7 +161,7 @@ pub fn layout_of_ty_query<'db>( trait_env: Arc>, ) -> Result, LayoutError> { let krate = trait_env.krate; - let interner = DbInterner::new_with(db, Some(krate), trait_env.block); + let interner = DbInterner::new_with(db, krate, trait_env.block); let Ok(target) = db.target_data_layout(krate) else { return Err(LayoutError::TargetLayoutNotAvailable); }; @@ -401,7 +401,7 @@ fn field_ty<'a>( fd: LocalFieldId, args: &GenericArgs<'a>, ) -> Ty<'a> { - db.field_types(def)[fd].instantiate(DbInterner::new_with(db, None, None), args) + db.field_types(def)[fd].instantiate(DbInterner::new_no_crate(db), args) } fn scalar_unit(dl: &TargetDataLayout, value: Primitive) -> Scalar { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs index f0fed8359729..2ce0a6792099 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout/tests.rs @@ -80,7 +80,7 @@ fn eval_goal( }) .unwrap(); crate::attach_db(&db, || { - let interner = DbInterner::new_with(&db, None, None); + let interner = DbInterner::new_no_crate(&db); let goal_ty = match adt_or_type_alias_id { Either::Left(adt_id) => crate::next_solver::Ty::new_adt( interner, diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs index 8819307c539b..6d3adec6a834 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs @@ -477,14 +477,14 @@ pub fn callable_sig_from_fn_trait<'db>( trait_env: Arc>, 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 // - >::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/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs index 3f187d205da6..72e622bcb53a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs +++ b/src/tools/rust-analyzer/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, @@ -193,7 +193,8 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> { let in_binders = DebruijnIndex::ZERO; Self { db, - interner: DbInterner::new_with(db, Some(resolver.krate()), None), + 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> + 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, @@ -1101,7 +1095,7 @@ impl ValueTyDefId { /// the constructor function `(usize) -> Foo` which lives in the values /// namespace. pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBinder<'db, Ty<'db>> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); match def { TyDefId::BuiltinType(it) => EarlyBinder::bind(Ty::from_builtin_type(interner, it)), TyDefId::AdtId(it) => EarlyBinder::bind(Ty::new_adt( @@ -1116,7 +1110,7 @@ pub(crate) fn ty_query<'db>(db: &'db dyn HirDatabase, def: TyDefId) -> EarlyBind /// Build the declared type of a function. This should not need to look at the /// function body. fn type_for_fn<'db>(db: &'db dyn HirDatabase, def: FunctionId) -> EarlyBinder<'db, Ty<'db>> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); EarlyBinder::bind(Ty::new_fn_def( interner, CallableDefId::FunctionId(def).into(), @@ -1165,7 +1159,7 @@ fn type_for_struct_constructor<'db>( FieldsShape::Record => None, FieldsShape::Unit => Some(type_for_adt(db, def.into())), FieldsShape::Tuple => { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); Some(EarlyBinder::bind(Ty::new_fn_def( interner, CallableDefId::StructId(def).into(), @@ -1185,7 +1179,7 @@ fn type_for_enum_variant_constructor<'db>( FieldsShape::Record => None, FieldsShape::Unit => Some(type_for_adt(db, def.loc(db).parent.into())), FieldsShape::Tuple => { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); Some(EarlyBinder::bind(Ty::new_fn_def( interner, CallableDefId::EnumVariantId(def).into(), @@ -1216,7 +1210,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics_query<'db>( let type_alias_data = db.type_alias_signature(t); let mut diags = None; let resolver = t.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let inner = if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) { EarlyBinder::bind(Ty::new_foreign(interner, t.into())) } else { @@ -1244,7 +1238,7 @@ pub(crate) fn type_for_type_alias_with_diagnostics_cycle_result<'db>( db: &'db dyn HirDatabase, _adt: TypeAliasId, ) -> (EarlyBinder<'db, Ty<'db>>, Diagnostics) { - (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) + (EarlyBinder::bind(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed)), None) } pub(crate) fn impl_self_ty_query<'db>( @@ -1277,7 +1271,7 @@ pub(crate) fn impl_self_ty_with_diagnostics_cycle_result( db: &dyn HirDatabase, _impl_id: ImplId, ) -> (EarlyBinder<'_, Ty<'_>>, Diagnostics) { - (EarlyBinder::bind(Ty::new_error(DbInterner::new_with(db, None, None), ErrorGuaranteed)), None) + (EarlyBinder::bind(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed)), None) } pub(crate) fn const_param_ty_query<'db>(db: &'db dyn HirDatabase, def: ConstParamId) -> Ty<'db> { @@ -1292,7 +1286,7 @@ pub(crate) fn const_param_ty_with_diagnostics_query<'db>( let (parent_data, store) = db.generic_params_and_store(def.parent()); let data = &parent_data[def.local_id()]; let resolver = def.parent().resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let mut ctx = TyLoweringContext::new( db, &resolver, @@ -1313,10 +1307,9 @@ pub(crate) fn const_param_ty_with_diagnostics_query<'db>( pub(crate) fn const_param_ty_with_diagnostics_cycle_result<'db>( db: &'db dyn HirDatabase, _: crate::db::HirDatabaseData, - def: ConstParamId, + _def: ConstParamId, ) -> (Ty<'db>, Diagnostics) { - let resolver = def.parent().resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); (Ty::new_error(interner, ErrorGuaranteed), None) } @@ -1374,7 +1367,7 @@ pub(crate) fn generic_predicates_for_param<'db>( assoc_name: Option, ) -> EarlyBinder<'db, Box<[Clause<'db>]>> { let generics = generics(db, def); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let resolver = def.resolver(db); let mut ctx = TyLoweringContext::new( db, @@ -1401,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` @@ -1466,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); }; } @@ -1520,8 +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, interner.krate.expect("Must have interner.krate")); + let sized_trait = ctx.lang_items.Sized; if let Some(sized_trait) = sized_trait { let trait_ref = TraitRef::new_from_args( interner, @@ -1625,7 +1619,7 @@ pub(crate) fn trait_environment_query<'db>( def: GenericDefId, ) -> Arc> { let module = def.module(db); - let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block()); + 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() @@ -1663,7 +1657,7 @@ where { let generics = generics(db, def); let resolver = def.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let mut ctx = TyLoweringContext::new( db, &resolver, @@ -1671,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 = @@ -1811,7 +1805,7 @@ fn push_const_arg_has_type_predicates<'db>( predicates: &mut Vec>, generics: &Generics, ) { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let const_params_offset = generics.len_parent() + generics.len_lifetimes_self(); for (param_index, (param_idx, param_data)) in generics.iter_self_type_or_consts().enumerate() { if !matches!(param_data, TypeOrConstParamData::ConstParamData(_)) { @@ -1839,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>, args: &'subst GenericArgs<'db>, - resolver: &Resolver<'db>, ) -> Option> + Captures<'a> + Captures<'subst>> { - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); - let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate())?; + let interner = DbInterner::new_no_crate(db); + let sized_trait = lang_items.Sized?; let trait_self_idx = trait_self_param_idx(db, def); @@ -1992,7 +1986,7 @@ fn fn_sig_for_fn<'db>( ) -> EarlyBinder<'db, PolyFnSig<'db>> { let data = db.function_signature(def); let resolver = def.resolver(db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let mut ctx_params = TyLoweringContext::new( db, &resolver, @@ -2028,7 +2022,7 @@ fn fn_sig_for_fn<'db>( } fn type_for_adt<'db>(db: &'db dyn HirDatabase, adt: AdtId) -> EarlyBinder<'db, Ty<'db>> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let args = GenericArgs::identity_for_item(interner, adt.into()); let ty = Ty::new_adt(interner, adt, args); EarlyBinder::bind(ty) @@ -2043,7 +2037,7 @@ fn fn_sig_for_struct_constructor<'db>( let ret = type_for_adt(db, def.into()).skip_binder(); let inputs_and_output = - Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); + Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret))); EarlyBinder::bind(Binder::dummy(FnSig { abi: FnAbi::RustCall, c_variadic: false, @@ -2062,7 +2056,7 @@ fn fn_sig_for_enum_variant_constructor<'db>( let ret = type_for_adt(db, parent.into()).skip_binder(); let inputs_and_output = - Tys::new_from_iter(DbInterner::new_with(db, None, None), params.chain(Some(ret))); + Tys::new_from_iter(DbInterner::new_no_crate(db), params.chain(Some(ret))); EarlyBinder::bind(Binder::dummy(FnSig { abi: FnAbi::RustCall, c_variadic: false, @@ -2078,7 +2072,7 @@ pub(crate) fn associated_ty_item_bounds<'db>( ) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> { let type_alias_data = db.type_alias_signature(type_alias); let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db); - let interner = DbInterner::new_with(db, Some(resolver.krate()), None); + let interner = DbInterner::new_no_crate(db); let mut ctx = TyLoweringContext::new( db, &resolver, @@ -2139,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, @@ -2157,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_with(db, None, None); + 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)?; @@ -2171,7 +2166,7 @@ pub fn associated_type_shorthand_candidates( res: TypeNs, mut cb: impl FnMut(&Name, TypeAliasId) -> bool, ) -> Option { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); named_associated_type_shorthand_candidates(interner, def, res, None, |name, _, id| { cb(name, id).then_some(id) }) diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs index 6d3ce74aed9b..fe96b6832e08 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower/path.rs @@ -1100,7 +1100,7 @@ pub(crate) fn substs_from_args_and_bindings<'db>( explicit_self_ty: Option>, ctx: &mut impl GenericArgsLowerer<'db>, ) -> GenericArgs<'db> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); tracing::debug!(?args_and_bindings); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs index 59299f2c35b7..4ec01e61b865 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution.rs @@ -418,7 +418,7 @@ pub(crate) fn lookup_impl_method_query<'db>( func: FunctionId, fn_subst: GenericArgs<'db>, ) -> (FunctionId, GenericArgs<'db>) { - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, env.krate, env.block); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let ItemContainerId::TraitId(trait_id) = func.loc(db).container else { @@ -597,7 +597,7 @@ impl InherentImpls { continue; } - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let self_ty = db.impl_self_ty(impl_id); let self_ty = self_ty.instantiate_identity(); if let Some(self_ty) = @@ -723,7 +723,7 @@ impl TraitImpls { None => continue, }; let self_ty = trait_ref.self_ty(); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let entry = map.entry(trait_ref.def_id.0).or_default(); match simplify_type(interner, self_ty, TreatParams::InstantiateWithInfer) { Some(self_ty) => { diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution/confirm.rs b/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution/confirm.rs index 9017c2f8777b..570dd63a50eb 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/method_resolution/confirm.rs +++ b/src/tools/rust-analyzer/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>, ) -> 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/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs index b5b691d4668e..317578fcd9fd 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs @@ -134,7 +134,7 @@ impl<'db> Operand<'db> { func_id: hir_def::FunctionId, generic_args: GenericArgs<'db>, ) -> Operand<'db> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let ty = Ty::new_fn_def(interner, CallableDefId::FunctionId(func_id).into(), generic_args); Operand::from_bytes(Box::default(), ty) } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs index 01892657bc21..acd064598a42 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs @@ -97,7 +97,7 @@ pub fn borrowck_query<'db>( ) -> Result]>, MirLowerError<'db>> { let _p = tracing::info_span!("borrowck_query").entered(); let module = def.module(db); - let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block()); + let interner = DbInterner::new_with(db, module.krate(), module.containing_block()); let env = db.trait_environment_for_body(def); let mut res = vec![]; // This calculates opaques defining scope which is a bit costly therefore is put outside `all_mir_bodies()`. @@ -124,7 +124,7 @@ fn make_fetch_closure_field<'db>( let infer = db.infer(def); let (captures, _) = infer.closure_info(c); let parent_subst = subst.split_closure_args_untupled().parent_args; - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); captures.get(f).expect("broken closure field").ty.instantiate(interner, parent_subst) } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs index da15ca695ea8..7e3a120c06a3 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs @@ -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}, @@ -641,8 +641,9 @@ impl<'db> Evaluator<'db> { Err(e) => return Err(MirEvalError::TargetDataLayoutNotAvailable(e)), }; let cached_ptr_size = target_data_layout.pointer_size().bytes_usize(); - let interner = DbInterner::new_with(db, Some(crate_id), module.containing_block()); + 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/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs index 4b1adecf8c87..c61afd62c4df 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs @@ -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> { // `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 { - use LangItem::*; + fn detect_lang_function(&self, def: FunctionId) -> Option { + 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> { - 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/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs index 88acd4906562..bb2afb2f0060 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs @@ -17,7 +17,7 @@ use super::{MirEvalError, interpret_mir}; fn eval_main(db: &TestDB, file_id: EditionedFileId) -> Result<(String, String), MirEvalError<'_>> { crate::attach_db(db, || { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let module_id = db.module_for_file(file_id.file_id(db)); let def_map = module_id.def_map(db); let scope = &def_map[module_id.local_id].scope; diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs index 7f457ca59ae8..be2291a62c9c 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs @@ -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:?}")?, @@ -302,7 +302,7 @@ impl<'a, 'db> MirLowerCtx<'a, 'db> { }; let resolver = owner.resolver(db); let env = db.trait_environment_for_body(owner); - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, env.krate, env.block); // FIXME(next-solver): Is `non_body_analysis()` correct here? Don't we want to reveal opaque types defined by this body? let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); @@ -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/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs index bceafae0f139..40c6c5de795a 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs index 745f73948d08..754d539e2086 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs @@ -98,7 +98,7 @@ impl<'db> Filler<'db> { env: Arc>, subst: GenericArgs<'db>, ) -> Self { - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, env.krate, env.block); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); Self { infcx, trait_env: env, subst } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs index fcce04fb08f6..443191423a88 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/infer/mod.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs index a3c984f6c981..82c4235b2f50 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/interner.rs +++ b/src/tools/rust-analyzer/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, pub(crate) block: Option, + lang_items: Option<&'db LangItems>, } // FIXME: very wrong, see https://github.com/rust-lang/rust/pull/144808 @@ -285,21 +286,48 @@ 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, lang_items: None } + } + pub fn new_with( db: &'db dyn HirDatabase, - krate: Option, + krate: Crate, block: Option, ) -> DbInterner<'db> { - DbInterner { db, 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 `()` @@ -849,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 ),* $(,)? @@ -857,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 { @@ -864,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; @@ -1253,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! */ }; @@ -1428,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 { @@ -1514,53 +1546,101 @@ 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)) - } - - fn is_adt_lang_item(self, def_id: Self::AdtId, lang_item: SolverAdtLangItem) -> bool { - // FIXME: derive PartialEq on SolverTraitLangItem - self.as_adt_lang_item(def_id) - .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item)) - } - - fn as_lang_item(self, def_id: Self::DefId) -> Option { - 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; - - ignore = { - AsyncFnKindUpvars, - } - - Metadata, - DynMetadata, - CoroutineReturn, - CoroutineYield, - FutureOutput, - CallRefFuture, - CallOnceFuture, - AsyncFnOnceOutput, - ) - } - - fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option { - let def_id: AttrDefId = def_id.0.into(); - let lang_item = self.db().lang_attr(def_id)?; - as_lang_item!( - SolverTraitLangItem, 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 { + // FIXME: derive PartialEq on SolverTraitLangItem + self.as_adt_lang_item(def_id) + .map_or(false, |l| std::mem::discriminant(&l) == std::mem::discriminant(&lang_item)) + } + + fn as_lang_item(self, def_id: Self::DefId) -> Option { + match def_id { + SolverDefId::TypeAliasId(id) => { + as_lang_item!( + SolverLangItem, self, id; + + 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, + } + + DynMetadata, + ) + } + _ => panic!("Unexpected SolverDefId in as_lang_item"), + } + } + + fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option { + as_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, @@ -1586,15 +1666,15 @@ impl<'db> Interner for DbInterner<'db> { AsyncFn, AsyncFnMut, AsyncFnOnce, - AsyncFnOnceOutput, ) } fn as_adt_lang_item(self, def_id: Self::AdtId) -> Option { - 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/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs b/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs index 58849ce9ca4c..c0a7c9adc485 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/next_solver/ty.rs +++ b/src/tools/rust-analyzer/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}; @@ -620,7 +619,7 @@ impl<'db> Ty<'db> { // FIXME: Should this be here? pub fn impl_trait_bounds(self, db: &'db dyn HirDatabase) -> Option>> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); match self.kind() { TyKind::Alias(AliasTyKind::Opaque, opaque_ty) => Some( @@ -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/src/tools/rust-analyzer/crates/hir-ty/src/opaques.rs b/src/tools/rust-analyzer/crates/hir-ty/src/opaques.rs index acf532c5e44a..fa99013d5e95 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/opaques.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/opaques.rs @@ -118,7 +118,7 @@ pub(crate) fn tait_hidden_types<'db>( let loc = type_alias.loc(db); let module = loc.module(db); - let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block()); + let interner = DbInterner::new_with(db, module.krate(), module.containing_block()); let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); let mut ocx = ObligationCtxt::new(&infcx); let cause = ObligationCause::dummy(); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/specialization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/specialization.rs index 304679d3729f..b69b43767724 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/specialization.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/specialization.rs @@ -46,7 +46,7 @@ fn specializes_query( parent_impl_def_id: ImplId, ) -> bool { let trait_env = db.trait_environment(specializing_impl_def_id.into()); - let interner = DbInterner::new_with(db, Some(trait_env.krate), trait_env.block); + let interner = DbInterner::new_with(db, trait_env.krate, trait_env.block); let specializing_impl_signature = db.impl_signature(specializing_impl_def_id); let parent_impl_signature = db.impl_signature(parent_impl_def_id); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs index e98e5e48284d..62ca2a05922b 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/incremental.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs index 2055c3151c6f..386a95eeb797 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/traits.rs +++ b/src/tools/rust-analyzer/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 { - 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 { - self.lang_item().resolve_trait(db, krate) + pub fn get_id(self, lang_items: &LangItems) -> Option { + 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, + } } } @@ -257,7 +216,7 @@ fn implements_trait_unique_impl<'db>( trait_: TraitId, create_args: &mut dyn FnMut(&InferCtxt<'db>) -> GenericArgs<'db>, ) -> bool { - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, env.krate, env.block); // FIXME(next-solver): I believe this should be `PostAnalysis`. let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs b/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs index ca5e33fe6ad0..820ccd990856 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/utils.rs +++ b/src/tools/rust-analyzer/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 + '_ { - [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 + '_ { + [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/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs index b57bf03f2472..df9d53f3e579 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/variance.rs @@ -32,7 +32,7 @@ use crate::{ pub(crate) fn variances_of(db: &dyn HirDatabase, def: GenericDefId) -> VariancesOf<'_> { tracing::debug!("variances_of(def={:?})", def); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); match def { GenericDefId::FunctionId(_) => (), GenericDefId::AdtId(adt) => { @@ -107,7 +107,7 @@ pub(crate) fn variances_of_cycle_initial( db: &dyn HirDatabase, def: GenericDefId, ) -> VariancesOf<'_> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let generics = generics(db, def); let count = generics.len(); diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs index cfc408038d8a..f1ca6cc4a9c6 100644 --- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs +++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs @@ -271,7 +271,7 @@ fn resolve_impl_trait_item<'db>( // attributes here. Use path resolution directly instead. // // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates) - let interner = DbInterner::new_with(db, Some(environment.krate), environment.block); + let interner = DbInterner::new_with(db, environment.krate, environment.block); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let unstable_features = MethodResolutionUnstableFeatures::from_def_map(resolver.top_level_def_map()); diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs index c215438aada4..10a1fa12e01a 100644 --- a/src/tools/rust-analyzer/crates/hir/src/display.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs index 2d70a8dca1d7..4c21b9806617 100644 --- a/src/tools/rust-analyzer/crates/hir/src/lib.rs +++ b/src/tools/rust-analyzer/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}, @@ -765,7 +766,7 @@ impl Module { } self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m)); - let interner = DbInterner::new_with(db, Some(self.id.krate()), self.id.containing_block()); + let interner = DbInterner::new_with(db, self.id.krate(), self.id.containing_block()); let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); let mut impl_assoc_items_scratch = vec![]; @@ -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; } @@ -1282,8 +1283,7 @@ pub struct InstantiatedField<'db> { impl<'db> InstantiatedField<'db> { /// Returns the type as in the signature of the struct. pub fn ty(&self, db: &'db dyn HirDatabase) -> TypeNs<'db> { - let krate = self.inner.krate(db); - let interner = DbInterner::new_with(db, Some(krate.base()), None); + let interner = DbInterner::new_no_crate(db); let var_id = self.inner.parent.into(); let field = db.field_types(var_id)[self.inner.id]; @@ -1305,7 +1305,7 @@ impl TupleField { } pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let ty = db .infer(self.owner) .tuple_field_access_type(self.tuple) @@ -1381,7 +1381,7 @@ impl Field { VariantDef::Union(it) => it.id.into(), VariantDef::Variant(it) => it.parent_enum(db).id.into(), }; - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let args = generic_args_from_tys(interner, def_id.into(), generics.map(|ty| ty.ty)); let ty = db.field_types(var_id)[self.id].instantiate(interner, args); Type::new(db, var_id, ty) @@ -1506,8 +1506,7 @@ impl<'db> InstantiatedStruct<'db> { } pub fn ty(self, db: &'db dyn HirDatabase) -> TypeNs<'db> { - let krate = self.inner.krate(db); - let interner = DbInterner::new_with(db, Some(krate.base()), None); + let interner = DbInterner::new_no_crate(db); let ty = db.ty(self.inner.id.into()); TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args)) @@ -1605,7 +1604,7 @@ impl Enum { /// The type of the enum variant bodies. pub fn variant_body_ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); Type::new_for_crate( self.id.lookup(db).container.krate(), match db.enum_signature(self.id).variant_body_type() { @@ -1669,8 +1668,7 @@ pub struct InstantiatedEnum<'db> { impl<'db> InstantiatedEnum<'db> { pub fn ty(self, db: &'db dyn HirDatabase) -> TypeNs<'db> { - let krate = self.inner.krate(db); - let interner = DbInterner::new_with(db, Some(krate.base()), None); + let interner = DbInterner::new_no_crate(db); let ty = db.ty(self.inner.id.into()); TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args)) @@ -1816,7 +1814,7 @@ impl Adt { pub fn layout(self, db: &dyn HirDatabase) -> Result { let env = db.trait_environment(self.into()); - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_no_crate(db); let adt_id = AdtId::from(self); let args = GenericArgs::for_item_with_defaults(interner, adt_id.into(), |_, id, _| { GenericArg::error_from_id(interner, id) @@ -1841,7 +1839,7 @@ impl Adt { args: impl IntoIterator>, ) -> Type<'db> { let id = AdtId::from(self); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let ty = Ty::new_adt( interner, id, @@ -2277,7 +2275,7 @@ impl Function { pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.resolver(db); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s. let callable_sig = db.callable_item_signature(self.id.into()).instantiate_identity(); let ty = Ty::new_fn_ptr(interner, callable_sig); @@ -2305,10 +2303,10 @@ impl Function { generics: impl Iterator>, ) -> Type<'db> { let resolver = self.id.resolver(db); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty)); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let ty = db .callable_item_signature(self.id.into()) .instantiate(interner, args) @@ -2396,7 +2394,7 @@ impl Function { generics: impl Iterator>, ) -> Vec> { let environment = db.trait_environment(self.id.into()); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty)); let callable_sig = db.callable_item_signature(self.id.into()).instantiate(interner, args).skip_binder(); @@ -2439,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; }; @@ -2547,7 +2545,7 @@ impl Function { db: &dyn HirDatabase, span_formatter: impl Fn(FileId, TextRange) -> String, ) -> Result> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let body = db.monomorphized_mir_body( self.id.into(), GenericArgs::new_from_iter(interner, []), @@ -2704,7 +2702,7 @@ impl SelfParam { db: &'db dyn HirDatabase, generics: impl Iterator>, ) -> Type<'db> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let args = generic_args_from_tys(interner, self.func.into(), generics.map(|ty| ty.ty)); let callable_sig = db.callable_item_signature(self.func.into()).instantiate(interner, args).skip_binder(); @@ -2804,7 +2802,7 @@ impl Const { /// Evaluate the constant. pub fn eval(self, db: &dyn HirDatabase) -> Result, ConstEvalError<'_>> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity(); db.const_eval(self.id, GenericArgs::new_from_iter(interner, []), None) .map(|it| EvaluatedConst { const_: it, def: self.id.into(), ty }) @@ -2908,8 +2906,12 @@ pub struct Trait { } impl Trait { - pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option { - LangItem::from_name(name)?.resolve_trait(db, krate.into()).map(Into::into) + pub fn lang(db: &dyn HirDatabase, krate: Crate, lang_item: LangItem) -> Option { + 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 { @@ -3076,7 +3078,7 @@ impl BuiltinType { pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> { let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); Type::new_for_crate(core, Ty::from_builtin_type(interner, self.inner)) } @@ -4208,7 +4210,7 @@ impl TypeParam { pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> { let resolver = self.id.parent().resolver(db); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let index = hir_ty::param_idx(db, self.id.into()).unwrap(); let ty = Ty::new_param(interner, self.id, index as u32); Type::new_with_resolver_inner(db, &resolver, ty) @@ -4412,9 +4414,12 @@ impl Impl { /// blanket impls, and only does a shallow type constructor check. In fact, this should've probably been on `Adt` /// etc., and not on `Type`. If you would want to create a precise list of all impls applying to a type, /// you would need to include blanket impls, and try to prove to predicates for each candidate. - pub fn all_for_type<'db>(db: &'db dyn HirDatabase, Type { ty, env }: Type<'db>) -> Vec { + pub fn all_for_type<'db>( + db: &'db dyn HirDatabase, + Type { ty, env: _ }: Type<'db>, + ) -> Vec { let mut result = Vec::new(); - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_no_crate(db); let Some(simplified_ty) = fast_reject::simplify_type(interner, ty, fast_reject::TreatParams::AsRigid) else { @@ -4591,7 +4596,7 @@ pub struct Closure<'db> { impl<'db> Closure<'db> { fn as_ty(&self, db: &'db dyn HirDatabase) -> Ty<'db> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); match self.id { AnyClosureId::ClosureId(id) => Ty::new_closure(interner, id.into(), self.subst), AnyClosureId::CoroutineClosureId(id) => { @@ -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 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::lang(db, krate, self.lang_item()) + } +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct ClosureCapture<'db> { owner: DefWithBodyId, @@ -4821,7 +4891,7 @@ impl<'db> Type<'db> { } fn from_def(db: &'db dyn HirDatabase, def: impl Into + HasResolver) -> Self { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let ty = db.ty(def.into()); let def = match def.into() { TyDefId::AdtId(it) => GenericDefId::AdtId(it), @@ -4844,7 +4914,7 @@ impl<'db> Type<'db> { db: &'db dyn HirDatabase, def: impl Into + HasResolver, ) -> Self { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let Some(ty) = db.value_ty(def.into()) else { return Type::new(db, def, Ty::new_error(interner, ErrorGuaranteed)); }; @@ -4900,7 +4970,7 @@ impl<'db> Type<'db> { } pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); return self.ty.visit_with(&mut Visitor { interner }).is_break(); fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool { @@ -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> { - 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> { - 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> { - 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 `::IntoIter` and returns the resulting type pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option> { - 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, }; @@ -5127,7 +5201,7 @@ impl<'db> Type<'db> { // FIXME: Find better API that also handles const generics pub fn impls_trait(&self, db: &'db dyn HirDatabase, trait_: Trait, args: &[Type<'db>]) -> bool { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let args = generic_args_from_tys( interner, trait_.id.into(), @@ -5142,7 +5216,7 @@ impl<'db> Type<'db> { args: &[Type<'db>], alias: TypeAlias, ) -> Option> { - let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block); + let interner = DbInterner::new_with(db, self.env.krate, self.env.block); let args = generic_args_from_tys( interner, alias.id.into(), @@ -5161,14 +5235,15 @@ 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(), &[]) } pub fn as_callable(&self, db: &'db dyn HirDatabase) -> Option> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let callee = match self.ty.kind() { TyKind::Closure(id, subst) => Callee::Closure(id.0, subst), TyKind::CoroutineClosure(id, subst) => Callee::CoroutineClosure(id.0, subst), @@ -5242,7 +5317,7 @@ impl<'db> Type<'db> { } pub fn fields(&self, db: &'db dyn HirDatabase) -> Vec<(Field, Self)> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let (variant_id, substs) = match self.ty.kind() { TyKind::Adt(adt_def, substs) => { let id = match adt_def.def_id().0 { @@ -5299,7 +5374,7 @@ impl<'db> Type<'db> { } fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); // There should be no inference vars in types passed here let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty); autoderef(db, self.env.clone(), canonical) @@ -5335,7 +5410,7 @@ impl<'db> Type<'db> { } }; - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let Some(simplified_type) = fast_reject::simplify_type(interner, self.ty, fast_reject::TreatParams::AsRigid) else { @@ -5484,7 +5559,7 @@ impl<'db> Type<'db> { f: impl FnOnce(&MethodResolutionContext<'_, 'db>) -> R, ) -> R { let module = resolver.module(); - let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block()); + let interner = DbInterner::new_with(db, module.krate(), module.containing_block()); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let unstable_features = MethodResolutionUnstableFeatures::from_def_map(resolver.top_level_def_map()); @@ -5781,7 +5856,7 @@ impl<'db> Type<'db> { /// Note that we consider placeholder types to unify with everything. /// For example `Option` and `Option` unify although there is unresolved goal `T = U`. pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty)); hir_ty::could_unify(db, self.env.clone(), &tys) } @@ -5791,13 +5866,13 @@ impl<'db> Type<'db> { /// This means that placeholder types are not considered to unify if there are any bounds set on /// them. For example `Option` and `Option` do not unify as we cannot show that `T = U` pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty)); hir_ty::could_unify_deeply(db, self.env.clone(), &tys) } pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, to.ty)); hir_ty::could_coerce(db, self.env.clone(), &tys) } @@ -5823,7 +5898,7 @@ impl<'db> Type<'db> { } pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue { - let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block); + let interner = DbInterner::new_with(db, self.env.krate, self.env.block); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); hir_ty::drop::has_drop_glue(&infcx, self.ty, self.env.clone()) } @@ -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/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs index 67b2d4a03369..220a3bf4321b 100644 --- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs @@ -1655,7 +1655,7 @@ impl<'db> SemanticsImpl<'db> { func: Function, subst: impl IntoIterator>, ) -> Option { - let interner = DbInterner::new_with(self.db, None, None); + let interner = DbInterner::new_no_crate(self.db); let mut subst = subst.into_iter(); let substs = hir_ty::next_solver::GenericArgs::for_item(interner, trait_.id.into(), |_, id, _| { diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs index 858426ceab73..f29e4ccf6070 100644 --- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs +++ b/src/tools/rust-analyzer/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}, @@ -267,7 +267,7 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, ty: &ast::Type, ) -> Option> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let type_ref = self.type_id(ty)?; @@ -410,7 +410,7 @@ impl<'db> SourceAnalyzer<'db> { ) -> Option> { let expr_id = self.expr_id(call.clone().into())?.as_expr()?; let (func, args) = self.infer()?.method_resolution(expr_id)?; - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let ty = db.value_ty(func.into())?.instantiate(interner, args); let ty = Type::new_with_resolver(db, &self.resolver, ty); let mut res = ty.as_callable(db)?; @@ -589,10 +589,10 @@ 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_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let substs = GenericArgs::new_from_iter(interner, [ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, poll_fn, substs)) } @@ -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,16 +626,16 @@ 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))? } }; let ty = self.ty_of_expr(prefix_expr.expr()?)?; - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); // HACK: subst for all methods coincides with that for their trait because the methods // don't have any generic parameters, so we skip building another subst for the methods. let substs = GenericArgs::new_from_iter(interner, [ty.into()]); @@ -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 } @@ -665,7 +668,7 @@ impl<'db> SourceAnalyzer<'db> { .unwrap_or(index_fn); // HACK: subst for all methods coincides with that for their trait because the methods // don't have any generic parameters, so we skip building another subst for the methods. - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let substs = GenericArgs::new_from_iter(interner, [base_ty.into(), index_ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) } @@ -679,12 +682,13 @@ 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_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let substs = GenericArgs::new_from_iter(interner, [lhs.into(), rhs.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) @@ -697,10 +701,10 @@ impl<'db> SourceAnalyzer<'db> { ) -> Option { 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_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let substs = GenericArgs::new_from_iter(interner, [ty.into()]); Some(self.resolve_impl_method_or_trait_def(db, op_fn, substs)) @@ -714,7 +718,7 @@ impl<'db> SourceAnalyzer<'db> { let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?; let expr = ast::Expr::from(record_expr); let expr_id = self.store_sm()?.node_expr(InFile::new(self.file_id, &expr))?; - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let ast_name = field.field_name()?; let local_name = ast_name.as_name(); @@ -755,7 +759,7 @@ impl<'db> SourceAnalyzer<'db> { db: &'db dyn HirDatabase, field: &ast::RecordPatField, ) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let field_name = field.field_name()?.as_name(); let record_pat = ast::RecordPat::cast(field.syntax().parent().and_then(|p| p.parent())?)?; let pat_id = self.pat_id(&record_pat.into())?; @@ -817,7 +821,7 @@ impl<'db> SourceAnalyzer<'db> { let trait_env = container.env; - let interner = DbInterner::new_with(db, Some(trait_env.krate), trait_env.block); + let interner = DbInterner::new_with(db, trait_env.krate, trait_env.block); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); let mut container = Either::Right(container.ty); @@ -1273,7 +1277,7 @@ impl<'db> SourceAnalyzer<'db> { variant: VariantId, missing_fields: Vec, ) -> Vec<(Field, Type<'db>)> { - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let field_types = db.field_types(variant); missing_fields @@ -1423,18 +1427,22 @@ impl<'db> SourceAnalyzer<'db> { None => return (const_id, subs), }; let env = db.trait_environment_for_body(owner); - let interner = DbInterner::new_with(db, Some(env.krate), env.block); + let interner = DbInterner::new_with(db, env.krate, env.block); let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis); 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, 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/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs index dddc03585a28..979ec8c49fe7 100644 --- a/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs +++ b/src/tools/rust-analyzer/crates/hir/src/term_search/tactics.rs @@ -597,7 +597,7 @@ pub(super) fn famous_types<'a, 'lt, 'db, DB: HirDatabase>( ) -> impl Iterator> + use<'a, 'db, 'lt, DB> { let db = ctx.sema.db; let module = ctx.scope.module(); - let interner = DbInterner::new_with(db, None, None); + let interner = DbInterner::new_no_crate(db); let bool_ty = Ty::new_bool(interner); let unit_ty = Ty::new_unit(interner); [ diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs index 6a868239cb20..fa87a499332b 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_from_impl_for_enum.rs @@ -123,7 +123,7 @@ fn existing_from_impl( let variant = sema.to_def(variant)?; let krate = variant.module(db).krate(); let from_trait = FamousDefs(sema, krate).core_convert_From()?; - let interner = DbInterner::new_with(db, Some(krate.base()), None); + let interner = DbInterner::new_with(db, krate.base(), None); use hir::next_solver::infer::DbInternerInferExt; let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs index a1ec76336566..9e87ec00dc01 100644 --- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs +++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_single_field_struct_from.rs @@ -220,7 +220,7 @@ fn from_impl_exists( let strukt = sema.to_def(strukt)?; let krate = strukt.krate(db); let from_trait = FamousDefs(sema, krate).core_convert_From()?; - let interner = DbInterner::new_with(db, Some(krate.base()), None); + let interner = DbInterner::new_with(db, krate.base(), None); use hir::next_solver::infer::DbInternerInferExt; let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis()); diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs index e139a5e27088..155f0b5a9815 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs index fa4b4b6d24be..dae2136f256b 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover.rs +++ b/src/tools/rust-analyzer/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/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs index a1eff3aaee78..8c2d3f0e5fbd 100644 --- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs +++ b/src/tools/rust-analyzer/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, diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs index 59a4de953c6e..219fc9eb0b8f 100644 --- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs @@ -10,8 +10,8 @@ use std::{ use cfg::{CfgAtom, CfgDiff}; use hir::{ - Adt, AssocItem, Crate, DefWithBody, FindPathConfig, HasCrate, HasSource, HirDisplay, ModuleDef, - Name, crate_lang_items, + Adt, AssocItem, Crate, DefWithBody, FindPathConfig, HasSource, HirDisplay, ModuleDef, Name, + crate_lang_items, db::{DefDatabase, ExpandDatabase, HirDatabase}, next_solver::{DbInterner, GenericArgs}, }; @@ -374,7 +374,7 @@ impl flags::AnalysisStats { let mut all = 0; let mut fail = 0; for &a in adts { - let interner = DbInterner::new_with(db, Some(a.krate(db).base()), None); + let interner = DbInterner::new_no_crate(db); let generic_params = db.generic_params(a.into()); if generic_params.iter_type_or_consts().next().is_some() || generic_params.iter_lt().next().is_some()