Merge pull request #21149 from ChayimFriedman2/lang-items

perf: Use one query per crate for lang items, not one per lang item
This commit is contained in:
Chayim Refael Friedman 2025-11-29 16:19:38 +00:00 committed by GitHub
commit bc662f19bb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
60 changed files with 1034 additions and 1065 deletions

View file

@ -27,7 +27,6 @@ use crate::{
VariantId,
db::DefDatabase,
item_tree::block_item_tree_query,
lang_item::LangItem,
nameres::{ModuleOrigin, ModuleSource},
src::{HasChildSource, HasSource},
};
@ -209,8 +208,8 @@ impl Attrs {
}
#[inline]
pub fn lang_item(&self) -> Option<LangItem> {
self.by_key(sym::lang).string_value().and_then(LangItem::from_symbol)
pub fn lang_item(&self) -> Option<&Symbol> {
self.by_key(sym::lang).string_value()
}
#[inline]

View file

@ -24,7 +24,6 @@ use crate::{
hir::generics::GenericParams,
import_map::ImportMap,
item_tree::{ItemTree, file_item_tree_query},
lang_item::{self, LangItem},
nameres::crate_def_map,
signatures::{
ConstSignature, EnumSignature, FunctionSignature, ImplSignature, StaticSignature,
@ -254,10 +253,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
#[salsa::invoke_interned(AttrsWithOwner::attrs_query)]
fn attrs(&self, def: AttrDefId) -> Attrs;
#[salsa::transparent]
#[salsa::invoke(lang_item::lang_attr)]
fn lang_attr(&self, def: AttrDefId) -> Option<LangItem>;
// endregion:attrs
#[salsa::invoke(ImportMap::import_map_query)]

View file

@ -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 { <stmts>; }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(()) }`
/// and save the `<new_label>` to use it as a break target for desugaring of the `?` operator.
fn desugar_try_block(&mut self, e: BlockExpr) -> ExprId {
let try_from_output = self.lang_path(LangItem::TryTraitFromOutput);
let try_from_output = self.lang_path(self.lang_items().TryTraitFromOutput);
let label = self.alloc_label_desugared(Label {
name: Name::generate_new_name(self.store.labels.len()),
});
@ -1753,10 +1760,11 @@ impl ExprCollector<'_> {
/// }
/// ```
fn collect_for_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::ForExpr) -> ExprId {
let into_iter_fn = self.lang_path(LangItem::IntoIterIntoIter);
let iter_next_fn = self.lang_path(LangItem::IteratorNext);
let option_some = self.lang_path(LangItem::OptionSome);
let option_none = self.lang_path(LangItem::OptionNone);
let lang_items = self.lang_items();
let into_iter_fn = self.lang_path(lang_items.IntoIterIntoIter);
let iter_next_fn = self.lang_path(lang_items.IteratorNext);
let option_some = self.lang_path(lang_items.OptionSome);
let option_none = self.lang_path(lang_items.OptionNone);
let head = self.collect_expr_opt(e.iterable());
let into_iter_fn_expr =
self.alloc_expr(into_iter_fn.map_or(Expr::Missing, Expr::Path), syntax_ptr);
@ -1836,10 +1844,11 @@ impl ExprCollector<'_> {
/// }
/// ```
fn collect_try_operator(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::TryExpr) -> ExprId {
let try_branch = self.lang_path(LangItem::TryTraitBranch);
let cf_continue = self.lang_path(LangItem::ControlFlowContinue);
let cf_break = self.lang_path(LangItem::ControlFlowBreak);
let try_from_residual = self.lang_path(LangItem::TryTraitFromResidual);
let lang_items = self.lang_items();
let try_branch = self.lang_path(lang_items.TryTraitBranch);
let cf_continue = self.lang_path(lang_items.ControlFlowContinue);
let cf_break = self.lang_path(lang_items.ControlFlowBreak);
let try_from_residual = self.lang_path(lang_items.TryTraitFromResidual);
let operand = self.collect_expr_opt(e.expr());
let try_branch = self.alloc_expr(try_branch.map_or(Expr::Missing, Expr::Path), syntax_ptr);
let expr = self
@ -2773,11 +2782,10 @@ impl ExprCollector<'_> {
// Assume that rustc version >= 1.89.0 iff lang item `format_arguments` exists
// but `format_unsafe_arg` does not
let fmt_args =
|| crate::lang_item::lang_item(self.db, self.module.krate(), LangItem::FormatArguments);
let fmt_unsafe_arg =
|| crate::lang_item::lang_item(self.db, self.module.krate(), LangItem::FormatUnsafeArg);
let use_format_args_since_1_89_0 = fmt_args().is_some() && fmt_unsafe_arg().is_none();
let lang_items = self.lang_items();
let fmt_args = lang_items.FormatArguments;
let fmt_unsafe_arg = lang_items.FormatUnsafeArg;
let use_format_args_since_1_89_0 = fmt_args.is_some() && fmt_unsafe_arg.is_none();
let idx = if use_format_args_since_1_89_0 {
self.collect_format_args_impl(syntax_ptr, fmt, argmap, lit_pieces, format_options)
@ -2856,16 +2864,13 @@ impl ExprCollector<'_> {
// unsafe { ::core::fmt::UnsafeArg::new() }
// )
let new_v1_formatted = LangItem::FormatArguments.ty_rel_path(
self.db,
self.module.krate(),
let lang_items = self.lang_items();
let new_v1_formatted = self.ty_rel_lang_path(
lang_items.FormatArguments,
Name::new_symbol_root(sym::new_v1_formatted),
);
let unsafe_arg_new = LangItem::FormatUnsafeArg.ty_rel_path(
self.db,
self.module.krate(),
Name::new_symbol_root(sym::new),
);
let unsafe_arg_new =
self.ty_rel_lang_path(lang_items.FormatUnsafeArg, Name::new_symbol_root(sym::new));
let new_v1_formatted =
self.alloc_expr_desugared(new_v1_formatted.map_or(Expr::Missing, Expr::Path));
@ -3044,9 +3049,8 @@ impl ExprCollector<'_> {
// )
// }
let new_v1_formatted = LangItem::FormatArguments.ty_rel_path(
self.db,
self.module.krate(),
let new_v1_formatted = self.ty_rel_lang_path(
self.lang_items().FormatArguments,
Name::new_symbol_root(sym::new_v1_formatted),
);
let new_v1_formatted =
@ -3099,6 +3103,7 @@ impl ExprCollector<'_> {
placeholder: &FormatPlaceholder,
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
) -> ExprId {
let lang_items = self.lang_items();
let position = match placeholder.argument.index {
Ok(arg_index) => {
let (i, _) =
@ -3159,15 +3164,14 @@ impl ExprCollector<'_> {
let width =
RecordLitField { name: Name::new_symbol_root(sym::width), expr: width_expr };
self.alloc_expr_desugared(Expr::RecordLit {
path: LangItem::FormatPlaceholder.path(self.db, self.module.krate()).map(Box::new),
path: self.lang_path(lang_items.FormatPlaceholder).map(Box::new),
fields: Box::new([position, flags, precision, width]),
spread: None,
})
} else {
let format_placeholder_new = {
let format_placeholder_new = LangItem::FormatPlaceholder.ty_rel_path(
self.db,
self.module.krate(),
let format_placeholder_new = self.ty_rel_lang_path(
lang_items.FormatPlaceholder,
Name::new_symbol_root(sym::new),
);
match format_placeholder_new {
@ -3188,9 +3192,8 @@ impl ExprCollector<'_> {
)));
let fill = self.alloc_expr_desugared(Expr::Literal(Literal::Char(fill.unwrap_or(' '))));
let align = {
let align = LangItem::FormatAlignment.ty_rel_path(
self.db,
self.module.krate(),
let align = self.ty_rel_lang_path(
lang_items.FormatAlignment,
match alignment {
Some(FormatAlignment::Left) => Name::new_symbol_root(sym::Left),
Some(FormatAlignment::Right) => Name::new_symbol_root(sym::Right),
@ -3234,6 +3237,7 @@ impl ExprCollector<'_> {
count: &Option<FormatCount>,
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
) -> ExprId {
let lang_items = self.lang_items();
match count {
Some(FormatCount::Literal(n)) => {
let args = self.alloc_expr_desugared(Expr::Literal(Literal::Uint(
@ -3241,11 +3245,9 @@ impl ExprCollector<'_> {
// FIXME: Change this to Some(BuiltinUint::U16) once we drop support for toolchains < 1.88
None,
)));
let count_is = match LangItem::FormatCount.ty_rel_path(
self.db,
self.module.krate(),
Name::new_symbol_root(sym::Is),
) {
let count_is = match self
.ty_rel_lang_path(lang_items.FormatCount, Name::new_symbol_root(sym::Is))
{
Some(count_is) => self.alloc_expr_desugared(Expr::Path(count_is)),
None => self.missing_expr(),
};
@ -3259,11 +3261,9 @@ impl ExprCollector<'_> {
i as u128,
Some(BuiltinUint::Usize),
)));
let count_param = match LangItem::FormatCount.ty_rel_path(
self.db,
self.module.krate(),
Name::new_symbol_root(sym::Param),
) {
let count_param = match self
.ty_rel_lang_path(lang_items.FormatCount, Name::new_symbol_root(sym::Param))
{
Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
None => self.missing_expr(),
};
@ -3277,11 +3277,9 @@ impl ExprCollector<'_> {
self.missing_expr()
}
}
None => match LangItem::FormatCount.ty_rel_path(
self.db,
self.module.krate(),
Name::new_symbol_root(sym::Implied),
) {
None => match self
.ty_rel_lang_path(lang_items.FormatCount, Name::new_symbol_root(sym::Implied))
{
Some(count_param) => self.alloc_expr_desugared(Expr::Path(count_param)),
None => self.missing_expr(),
},
@ -3299,9 +3297,8 @@ impl ExprCollector<'_> {
use ArgumentType::*;
use FormatTrait::*;
let new_fn = match LangItem::FormatArgument.ty_rel_path(
self.db,
self.module.krate(),
let new_fn = match self.ty_rel_lang_path(
self.lang_items().FormatArgument,
Name::new_symbol_root(match ty {
Format(Display) => sym::new_display,
Format(Debug) => sym::new_debug,
@ -3323,8 +3320,16 @@ impl ExprCollector<'_> {
// endregion: format
fn lang_path(&self, lang: LangItem) -> Option<Path> {
lang.path(self.db, self.module.krate())
fn lang_path(&self, lang: Option<impl Into<LangItemTarget>>) -> Option<Path> {
Some(Path::LangItem(lang?.into(), None))
}
fn ty_rel_lang_path(
&self,
lang: Option<impl Into<LangItemTarget>>,
relative_name: Name,
) -> Option<Path> {
Some(Path::LangItem(lang?.into(), Some(relative_name)))
}
}

View file

@ -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 {

View file

@ -2,101 +2,36 @@
//!
//! This attribute to tell the compiler about semi built-in std library
//! features, such as Fn family of traits.
use hir_expand::name::Name;
use intern::{Symbol, sym};
use rustc_hash::FxHashMap;
use stdx::impl_from;
use crate::{
AdtId, AssocItemId, AttrDefId, Crate, EnumId, EnumVariantId, FunctionId, ImplId, ModuleDefId,
StaticId, StructId, TraitId, TypeAliasId, UnionId,
db::DefDatabase,
expr_store::path::Path,
nameres::{assoc::TraitItems, crate_def_map, crate_local_def_map},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum LangItemTarget {
EnumId(EnumId),
Function(FunctionId),
ImplDef(ImplId),
Static(StaticId),
Struct(StructId),
Union(UnionId),
TypeAlias(TypeAliasId),
Trait(TraitId),
EnumVariant(EnumVariantId),
FunctionId(FunctionId),
ImplId(ImplId),
StaticId(StaticId),
StructId(StructId),
UnionId(UnionId),
TypeAliasId(TypeAliasId),
TraitId(TraitId),
EnumVariantId(EnumVariantId),
}
impl LangItemTarget {
pub fn as_enum(self) -> Option<EnumId> {
match self {
LangItemTarget::EnumId(id) => Some(id),
_ => None,
}
}
pub fn as_function(self) -> Option<FunctionId> {
match self {
LangItemTarget::Function(id) => Some(id),
_ => None,
}
}
pub fn as_impl_def(self) -> Option<ImplId> {
match self {
LangItemTarget::ImplDef(id) => Some(id),
_ => None,
}
}
pub fn as_static(self) -> Option<StaticId> {
match self {
LangItemTarget::Static(id) => Some(id),
_ => None,
}
}
pub fn as_struct(self) -> Option<StructId> {
match self {
LangItemTarget::Struct(id) => Some(id),
_ => None,
}
}
pub fn as_trait(self) -> Option<TraitId> {
match self {
LangItemTarget::Trait(id) => Some(id),
_ => None,
}
}
pub fn as_enum_variant(self) -> Option<EnumVariantId> {
match self {
LangItemTarget::EnumVariant(id) => Some(id),
_ => None,
}
}
pub fn as_type_alias(self) -> Option<TypeAliasId> {
match self {
LangItemTarget::TypeAlias(id) => Some(id),
_ => None,
}
}
pub fn as_adt(self) -> Option<AdtId> {
match self {
LangItemTarget::Union(it) => Some(it.into()),
LangItemTarget::EnumId(it) => Some(it.into()),
LangItemTarget::Struct(it) => Some(it.into()),
_ => None,
}
}
}
impl_from!(
EnumId, FunctionId, ImplId, StaticId, StructId, UnionId, TypeAliasId, TraitId, EnumVariantId for LangItemTarget
);
/// Salsa query. This will look for lang items in a specific crate.
#[salsa_macros::tracked(returns(ref))]
pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangItems>> {
pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> LangItems {
let _p = tracing::info_span!("crate_lang_items_query").entered();
let mut lang_items = LangItems::default();
@ -105,15 +40,11 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
for (_, module_data) in crate_def_map.modules() {
for impl_def in module_data.scope.impls() {
lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
lang_items.collect_lang_item(db, impl_def);
for &(_, assoc) in impl_def.impl_items(db).items.iter() {
match assoc {
AssocItemId::FunctionId(f) => {
lang_items.collect_lang_item(db, f, LangItemTarget::Function)
}
AssocItemId::TypeAliasId(t) => {
lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
}
AssocItemId::FunctionId(f) => lang_items.collect_lang_item(db, f),
AssocItemId::TypeAliasId(t) => lang_items.collect_lang_item(db, t),
AssocItemId::ConstId(_) => (),
}
}
@ -122,62 +53,55 @@ pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangIt
for def in module_data.scope.declarations() {
match def {
ModuleDefId::TraitId(trait_) => {
lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
lang_items.collect_lang_item(db, trait_);
TraitItems::query(db, trait_).items.iter().for_each(|&(_, assoc_id)| {
match assoc_id {
AssocItemId::FunctionId(f) => {
lang_items.collect_lang_item(db, f, LangItemTarget::Function);
lang_items.collect_lang_item(db, f);
}
AssocItemId::TypeAliasId(alias) => {
lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
lang_items.collect_lang_item(db, alias)
}
AssocItemId::ConstId(_) => {}
}
});
}
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
lang_items.collect_lang_item(db, e);
e.enum_variants(db).variants.iter().for_each(|&(id, _, _)| {
lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
lang_items.collect_lang_item(db, id);
});
}
ModuleDefId::AdtId(AdtId::StructId(s)) => {
lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
lang_items.collect_lang_item(db, s);
}
ModuleDefId::AdtId(AdtId::UnionId(u)) => {
lang_items.collect_lang_item(db, u, LangItemTarget::Union);
lang_items.collect_lang_item(db, u);
}
ModuleDefId::FunctionId(f) => {
lang_items.collect_lang_item(db, f, LangItemTarget::Function);
lang_items.collect_lang_item(db, f);
}
ModuleDefId::StaticId(s) => {
lang_items.collect_lang_item(db, s, LangItemTarget::Static);
lang_items.collect_lang_item(db, s);
}
ModuleDefId::TypeAliasId(t) => {
lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
lang_items.collect_lang_item(db, t);
}
_ => {}
}
}
}
if lang_items.items.is_empty() { None } else { Some(Box::new(lang_items)) }
lang_items
}
/// Salsa query. Look for a lang item, starting from the specified crate and recursively
/// Salsa query. Look for a lang items, starting from the specified crate and recursively
/// traversing its dependencies.
#[salsa_macros::tracked]
pub fn lang_item(
db: &dyn DefDatabase,
start_crate: Crate,
item: LangItem,
) -> Option<LangItemTarget> {
let _p = tracing::info_span!("lang_item_query").entered();
if let Some(target) =
crate_lang_items(db, start_crate).as_ref().and_then(|it| it.items.get(&item).copied())
{
return Some(target);
}
#[salsa_macros::tracked(returns(ref))]
pub fn lang_items(db: &dyn DefDatabase, start_crate: Crate) -> LangItems {
let _p = tracing::info_span!("lang_items_query").entered();
let mut result = crate_lang_items(db, start_crate).clone();
// Our `CrateGraph` eagerly inserts sysroot dependencies like `core` or `std` into dependencies
// even if the target crate has `#![no_std]`, `#![no_core]` or shadowed sysroot dependencies
@ -186,42 +110,29 @@ pub fn lang_item(
// while nameres.
//
// See https://github.com/rust-lang/rust-analyzer/pull/20475 for details.
crate_local_def_map(db, start_crate).local(db).extern_prelude().find_map(|(_, (krate, _))| {
for (_, (krate, _)) in crate_local_def_map(db, start_crate).local(db).extern_prelude() {
// Some crates declares themselves as extern crate like `extern crate self as core`.
// Ignore these to prevent cycles.
if krate.krate == start_crate { None } else { lang_item(db, krate.krate, item) }
})
}
if krate.krate != start_crate {
result.merge_prefer_self(lang_items(db, krate.krate));
}
}
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct LangItems {
items: FxHashMap<LangItem, LangItemTarget>,
result
}
impl LangItems {
pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
self.items.get(&item).copied()
}
fn collect_lang_item<T>(
&mut self,
db: &dyn DefDatabase,
item: T,
constructor: fn(T) -> LangItemTarget,
) where
T: Into<AttrDefId> + Copy,
fn collect_lang_item<T>(&mut self, db: &dyn DefDatabase, item: T)
where
T: Into<AttrDefId> + Into<LangItemTarget> + Copy,
{
let _p = tracing::info_span!("collect_lang_item").entered();
if let Some(lang_item) = lang_attr(db, item.into()) {
self.items.entry(lang_item).or_insert_with(|| constructor(item));
if let Some(lang_item) = db.attrs(item.into()).lang_item() {
self.assign_lang_item(lang_item, item.into());
}
}
}
pub(crate) fn lang_attr(db: &dyn DefDatabase, item: AttrDefId) -> Option<LangItem> {
db.attrs(item).lang_item()
}
#[salsa::tracked(returns(as_deref))]
pub(crate) fn crate_notable_traits(db: &dyn DefDatabase, krate: Crate) -> Option<Box<[TraitId]>> {
let mut traits = Vec::new();
@ -249,173 +160,151 @@ pub enum GenericRequirement {
macro_rules! language_item_table {
(
$( $(#[$attr:meta])* $variant:ident, $module:ident :: $name:ident, $method:ident, $target:expr, $generics:expr; )*
$( $(#[$attr:meta])* $lang_item:ident, $module:ident :: $name:ident, $method:ident, $target:ident, $generics:expr; )*
) => {
/// A representation of all the valid language items in Rust.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum LangItem {
#[allow(non_snake_case)] // FIXME: Should we remove this?
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
pub struct LangItems {
$(
#[doc = concat!("The `", stringify!($name), "` lang item.")]
$(#[$attr])*
$variant,
pub $lang_item: Option<$target>,
)*
}
impl LangItem {
pub fn name(self) -> &'static str {
match self {
$( LangItem::$variant => stringify!($name), )*
}
impl LangItems {
/// Merges `self` with `other`, with preference to `self` items.
fn merge_prefer_self(&mut self, other: &Self) {
$( self.$lang_item = self.$lang_item.or(other.$lang_item); )*
}
/// Opposite of [`LangItem::name`]
pub fn from_symbol(sym: &Symbol) -> Option<Self> {
match sym {
$(sym if *sym == $module::$name => Some(LangItem::$variant), )*
_ => None,
fn assign_lang_item(&mut self, name: &Symbol, target: LangItemTarget) {
match name {
$(
_ if *name == $module::$name => {
if let LangItemTarget::$target(target) = target {
self.$lang_item = Some(target);
}
}
)*
_ => {}
}
}
}
}
}
impl LangItem {
pub fn resolve_function(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<FunctionId> {
lang_item(db, start_crate, self).and_then(|t| t.as_function())
}
#[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<TraitId> {
lang_item(db, start_crate, self).and_then(|t| t.as_trait())
}
pub fn resolve_adt(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<AdtId> {
lang_item(db, start_crate, self).and_then(|t| t.as_adt())
}
pub fn resolve_enum(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<EnumId> {
lang_item(db, start_crate, self).and_then(|t| t.as_enum())
}
pub fn resolve_type_alias(
self,
db: &dyn DefDatabase,
start_crate: Crate,
) -> Option<TypeAliasId> {
lang_item(db, start_crate, self).and_then(|t| t.as_type_alias())
}
/// Opposite of [`LangItem::name`]
pub fn from_name(name: &hir_expand::name::Name) -> Option<Self> {
Self::from_symbol(name.symbol())
}
pub fn path(&self, db: &dyn DefDatabase, start_crate: Crate) -> Option<Path> {
let t = lang_item(db, start_crate, *self)?;
Some(Path::LangItem(t, None))
}
pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option<Path> {
let t = lang_item(db, start_crate, *self)?;
Some(Path::LangItem(t, Some(seg)))
impl LangItemEnum {
#[inline]
pub fn from_lang_items(self, lang_items: &LangItems) -> Option<LangItemTarget> {
match self {
$( LangItemEnum::$lang_item => lang_items.$lang_item.map(Into::into), )*
}
}
}
}
}
language_item_table! {
// Variant name, Name, Getter method name, Target Generic requirements;
Sized, sym::sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
MetaSized, sym::meta_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
PointeeSized, sym::pointee_sized, sized_trait, Target::Trait, GenericRequirement::Exact(0);
Unsize, sym::unsize, unsize_trait, Target::Trait, GenericRequirement::Minimum(1);
Sized, sym::sized, sized_trait, TraitId, GenericRequirement::Exact(0);
MetaSized, sym::meta_sized, sized_trait, TraitId, GenericRequirement::Exact(0);
PointeeSized, sym::pointee_sized, sized_trait, TraitId, GenericRequirement::Exact(0);
Unsize, sym::unsize, unsize_trait, TraitId, GenericRequirement::Minimum(1);
/// Trait injected by `#[derive(PartialEq)]`, (i.e. "Partial EQ").
StructuralPeq, sym::structural_peq, structural_peq_trait, Target::Trait, GenericRequirement::None;
StructuralPeq, sym::structural_peq, structural_peq_trait, TraitId, GenericRequirement::None;
/// Trait injected by `#[derive(Eq)]`, (i.e. "Total EQ"; no, I will not apologize).
StructuralTeq, sym::structural_teq, structural_teq_trait, Target::Trait, GenericRequirement::None;
Copy, sym::copy, copy_trait, Target::Trait, GenericRequirement::Exact(0);
Clone, sym::clone, clone_trait, Target::Trait, GenericRequirement::None;
Sync, sym::sync, sync_trait, Target::Trait, GenericRequirement::Exact(0);
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, Target::Trait, GenericRequirement::None;
StructuralTeq, sym::structural_teq, structural_teq_trait, TraitId, GenericRequirement::None;
Copy, sym::copy, copy_trait, TraitId, GenericRequirement::Exact(0);
Clone, sym::clone, clone_trait, TraitId, GenericRequirement::None;
Sync, sym::sync, sync_trait, TraitId, GenericRequirement::Exact(0);
DiscriminantKind, sym::discriminant_kind, discriminant_kind_trait, TraitId, GenericRequirement::None;
/// The associated item of the [`DiscriminantKind`] trait.
Discriminant, sym::discriminant_type, discriminant_type, Target::AssocTy, GenericRequirement::None;
Discriminant, sym::discriminant_type, discriminant_type, TypeAliasId, GenericRequirement::None;
PointeeTrait, sym::pointee_trait, pointee_trait, Target::Trait, GenericRequirement::None;
Metadata, sym::metadata_type, metadata_type, Target::AssocTy, GenericRequirement::None;
DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None;
PointeeTrait, sym::pointee_trait, pointee_trait, TraitId, GenericRequirement::None;
Metadata, sym::metadata_type, metadata_type, TypeAliasId, GenericRequirement::None;
DynMetadata, sym::dyn_metadata, dyn_metadata, StructId, GenericRequirement::None;
Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
Freeze, sym::freeze, freeze_trait, TraitId, GenericRequirement::Exact(0);
FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, Target::Trait, GenericRequirement::Exact(0);
FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, TraitId, GenericRequirement::Exact(0);
FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, FunctionId, GenericRequirement::None;
Drop, sym::drop, drop_trait, Target::Trait, GenericRequirement::None;
Destruct, sym::destruct, destruct_trait, Target::Trait, GenericRequirement::None;
Drop, sym::drop, drop_trait, TraitId, GenericRequirement::None;
Destruct, sym::destruct, destruct_trait, TraitId, GenericRequirement::None;
CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, Target::Trait, GenericRequirement::Minimum(1);
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, Target::Trait, GenericRequirement::Minimum(1);
CoerceUnsized, sym::coerce_unsized, coerce_unsized_trait, TraitId, GenericRequirement::Minimum(1);
DispatchFromDyn, sym::dispatch_from_dyn, dispatch_from_dyn_trait, TraitId, GenericRequirement::Minimum(1);
// language items relating to transmutability
TransmuteOpts, sym::transmute_opts, transmute_opts, Target::Struct, GenericRequirement::Exact(0);
TransmuteTrait, sym::transmute_trait, transmute_trait, Target::Trait, GenericRequirement::Exact(3);
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;
}

View file

@ -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((

View file

@ -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,
_ => (),
}
}

View file

@ -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<TraitEnvironment<'db>>,
ty: Canonical<'db, Ty<'db>>,
) -> impl Iterator<Item = Ty<'db>> + 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<AutoderefTraits> {
let lang_items = self.interner().lang_items();
match &mut self.traits {
Some(it) => Some(*it),
None => {
let traits = if self.use_receiver_trait {
(|| {
Some(AutoderefTraits {
trait_: LangItem::Receiver
.resolve_trait(self.db(), self.env().krate)?,
trait_target: LangItem::ReceiverTarget
.resolve_type_alias(self.db(), self.env().krate)?,
trait_: lang_items.Receiver?,
trait_target: lang_items.ReceiverTarget?,
})
})()
.or_else(|| {
Some(AutoderefTraits {
trait_: LangItem::Deref.resolve_trait(self.db(), self.env().krate)?,
trait_target: LangItem::DerefTarget
.resolve_type_alias(self.db(), self.env().krate)?,
trait_: lang_items.Deref?,
trait_target: lang_items.DerefTarget?,
})
})?
} else {
AutoderefTraits {
trait_: LangItem::Deref.resolve_trait(self.db(), self.env().krate)?,
trait_target: LangItem::DerefTarget
.resolve_type_alias(self.db(), self.env().krate)?,
trait_: lang_items.Deref?,
trait_target: lang_items.DerefTarget?,
}
};
Some(*self.traits.insert(traits))

View file

@ -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<u128>, 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<i128, ConstEvalError<'db>> {
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<Const<'db>, 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, []),

View file

@ -123,7 +123,7 @@ fn pretty_print_err(e: ConstEvalError<'_>, db: &TestDB) -> String {
fn eval_goal(db: &TestDB, file_id: EditionedFileId) -> Result<Const<'_>, 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;

View file

@ -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 {

View file

@ -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<String, DisplaySourceCodeError> {
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<T: HirDisplay<'db>>(
&mut self,
iter: impl IntoIterator<Item = T>,
@ -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<Item = TraitId> + '_ {
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, " + ")?;

View file

@ -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 {

View file

@ -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<DynCompatibilityViolation> {
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<F>(
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<DbI
&mut self,
ty: <DbInterner<'db> 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;
};

View file

@ -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<InferenceResult<'_>> {
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<TraitId>,
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<LangItemTarget> {
let krate = self.resolver.krate();
lang_item(self.db, krate, item)
}
fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
trait_.trait_items(self.db).associated_type_by_name(&Name::new_symbol_root(sym::Output))
}
fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
let ItemContainerId::TraitId(trait_) = self
.resolve_lang_item(LangItem::IntoFutureIntoFuture)?
.as_function()?
.lookup(self.db)
.container
let ItemContainerId::TraitId(trait_) =
self.lang_items.IntoFutureIntoFuture?.lookup(self.db).container
else {
return None;
};
@ -1876,42 +1870,42 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
fn resolve_boxed_box(&self) -> Option<AdtId> {
let struct_ = self.resolve_lang_item(LangItem::OwnedBox)?.as_struct()?;
let struct_ = self.lang_items.OwnedBox?;
Some(struct_.into())
}
fn resolve_range_full(&self) -> Option<AdtId> {
let struct_ = self.resolve_lang_item(LangItem::RangeFull)?.as_struct()?;
let struct_ = self.lang_items.RangeFull?;
Some(struct_.into())
}
fn resolve_range(&self) -> Option<AdtId> {
let struct_ = self.resolve_lang_item(LangItem::Range)?.as_struct()?;
let struct_ = self.lang_items.Range?;
Some(struct_.into())
}
fn resolve_range_inclusive(&self) -> Option<AdtId> {
let struct_ = self.resolve_lang_item(LangItem::RangeInclusiveStruct)?.as_struct()?;
let struct_ = self.lang_items.RangeInclusiveStruct?;
Some(struct_.into())
}
fn resolve_range_from(&self) -> Option<AdtId> {
let struct_ = self.resolve_lang_item(LangItem::RangeFrom)?.as_struct()?;
let struct_ = self.lang_items.RangeFrom?;
Some(struct_.into())
}
fn resolve_range_to(&self) -> Option<AdtId> {
let struct_ = self.resolve_lang_item(LangItem::RangeTo)?.as_struct()?;
let struct_ = self.lang_items.RangeTo?;
Some(struct_.into())
}
fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
let struct_ = self.resolve_lang_item(LangItem::RangeToInclusive)?.as_struct()?;
let struct_ = self.lang_items.RangeToInclusive?;
Some(struct_.into())
}
fn resolve_va_list(&self) -> Option<AdtId> {
let struct_ = self.resolve_lang_item(LangItem::VaList)?.as_struct()?;
let struct_ = self.lang_items.VaList?;
Some(struct_.into())
}

View file

@ -7,7 +7,6 @@ use std::{iter, mem, ops::ControlFlow};
use hir_def::{
TraitId,
hir::{ClosureKind, ExprId, PatId},
lang_item::LangItem,
type_ref::TypeRefId,
};
use rustc_type_ir::{
@ -220,11 +219,12 @@ impl<'db> InferenceContext<'_, 'db> {
}
fn fn_trait_kind_from_def_id(&self, trait_id: TraitId) -> Option<rustc_type_ir::ClosureKind> {
let lang_item = self.db.lang_attr(trait_id.into())?;
match lang_item {
LangItem::Fn => Some(rustc_type_ir::ClosureKind::Fn),
LangItem::FnMut => Some(rustc_type_ir::ClosureKind::FnMut),
LangItem::FnOnce => Some(rustc_type_ir::ClosureKind::FnOnce),
match trait_id {
_ if self.lang_items.Fn == Some(trait_id) => Some(rustc_type_ir::ClosureKind::Fn),
_ if self.lang_items.FnMut == Some(trait_id) => Some(rustc_type_ir::ClosureKind::FnMut),
_ if self.lang_items.FnOnce == Some(trait_id) => {
Some(rustc_type_ir::ClosureKind::FnOnce)
}
_ => None,
}
}
@ -233,11 +233,14 @@ impl<'db> InferenceContext<'_, 'db> {
&self,
trait_id: TraitId,
) -> Option<rustc_type_ir::ClosureKind> {
let lang_item = self.db.lang_attr(trait_id.into())?;
match lang_item {
LangItem::AsyncFn => Some(rustc_type_ir::ClosureKind::Fn),
LangItem::AsyncFnMut => Some(rustc_type_ir::ClosureKind::FnMut),
LangItem::AsyncFnOnce => Some(rustc_type_ir::ClosureKind::FnOnce),
match trait_id {
_ if self.lang_items.AsyncFn == Some(trait_id) => Some(rustc_type_ir::ClosureKind::Fn),
_ if self.lang_items.AsyncFnMut == Some(trait_id) => {
Some(rustc_type_ir::ClosureKind::FnMut)
}
_ if self.lang_items.AsyncFnOnce == Some(trait_id) => {
Some(rustc_type_ir::ClosureKind::FnOnce)
}
_ => None,
}
}
@ -433,21 +436,20 @@ impl<'db> InferenceContext<'_, 'db> {
projection: PolyProjectionPredicate<'db>,
) -> Option<PolyFnSig<'db>> {
let SolverDefId::TypeAliasId(def_id) = projection.item_def_id() else { unreachable!() };
let lang_item = self.db.lang_attr(def_id.into());
// For now, we only do signature deduction based off of the `Fn` and `AsyncFn` traits,
// for closures and async closures, respectively.
match closure_kind {
ClosureKind::Closure if lang_item == Some(LangItem::FnOnceOutput) => {
ClosureKind::Closure if Some(def_id) == self.lang_items.FnOnceOutput => {
self.extract_sig_from_projection(projection)
}
ClosureKind::Async if lang_item == Some(LangItem::AsyncFnOnceOutput) => {
ClosureKind::Async if Some(def_id) == self.lang_items.AsyncFnOnceOutput => {
self.extract_sig_from_projection(projection)
}
// It's possible we've passed the closure to a (somewhat out-of-fashion)
// `F: FnOnce() -> Fut, Fut: Future<Output = T>` style bound. Let's still
// guide inference here, since it's beneficial for the user.
ClosureKind::Async if lang_item == Some(LangItem::FnOnceOutput) => {
ClosureKind::Async if Some(def_id) == self.lang_items.FnOnceOutput => {
self.extract_sig_from_projection_and_future_bound(projection)
}
_ => None,
@ -538,7 +540,7 @@ impl<'db> InferenceContext<'_, 'db> {
&& let ret_projection = bound.predicate.kind().rebind(ret_projection)
&& let Some(ret_projection) = ret_projection.no_bound_vars()
&& let SolverDefId::TypeAliasId(assoc_type) = ret_projection.def_id()
&& self.db.lang_attr(assoc_type.into()) == Some(LangItem::FutureOutput)
&& Some(assoc_type) == self.lang_items.FutureOutput
{
return_ty = Some(ret_projection.term.expect_type());
break;

View file

@ -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)
}

View file

@ -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<TraitEnvironment<'db>>,
tys: &Canonical<'db, (Ty<'db>, Ty<'db>)>,
) -> Result<(Vec<Adjustment<'db>>, Ty<'db>), TypeError<DbInterner<'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 ((ty1_with_vars, ty2_with_vars), vars) = infcx.instantiate_canonical(tys);

View file

@ -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);

View file

@ -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,

View file

@ -2,7 +2,7 @@
use std::collections::hash_map;
use hir_def::{GenericParamId, TraitId, hir::ExprId, lang_item::LangItem};
use hir_def::{GenericParamId, TraitId, hir::ExprId};
use intern::{Symbol, sym};
use rustc_ast_ir::Mutability;
use rustc_type_ir::inherent::{IntoKind, Ty as _};
@ -355,17 +355,18 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
fn lang_item_for_bin_op(&self, op: BinaryOp) -> (Symbol, Option<TraitId>) {
let (method_name, trait_lang_item) =
crate::lang_items::lang_items_for_bin_op(op).expect("invalid operator provided");
(method_name, trait_lang_item.resolve_trait(self.db, self.krate()))
crate::lang_items::lang_items_for_bin_op(self.lang_items, op)
.expect("invalid operator provided");
(method_name, trait_lang_item)
}
fn lang_item_for_unop(&self, op: UnaryOp) -> (Symbol, Option<TraitId>) {
let (method_name, trait_lang_item) = match op {
UnaryOp::Not => (sym::not, LangItem::Not),
UnaryOp::Neg => (sym::neg, LangItem::Neg),
UnaryOp::Not => (sym::not, self.lang_items.Not),
UnaryOp::Neg => (sym::neg, self.lang_items.Neg),
UnaryOp::Deref => panic!("Deref is not overloadable"),
};
(method_name, trait_lang_item.resolve_trait(self.db, self.krate()))
(method_name, trait_lang_item)
}
}

View file

@ -1,7 +1,6 @@
//! Inference of *place operators*: deref and indexing (operators that create places, as opposed to values).
use base_db::Crate;
use hir_def::{hir::ExprId, lang_item::LangItem};
use hir_def::hir::ExprId;
use intern::sym;
use rustc_ast_ir::Mutability;
use rustc_type_ir::inherent::{IntoKind, Ty as _};
@ -187,8 +186,8 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
debug!("try_overloaded_place_op({:?},{:?})", base_ty, op);
let (Some(imm_tr), imm_op) = (match op {
PlaceOp::Deref => (LangItem::Deref.resolve_trait(self.db, self.krate()), sym::deref),
PlaceOp::Index => (LangItem::Index.resolve_trait(self.db, self.krate()), sym::index),
PlaceOp::Deref => (self.lang_items.Deref, sym::deref),
PlaceOp::Index => (self.lang_items.Index, sym::index),
}) else {
// Bail if `Deref` or `Index` isn't defined.
return None;
@ -209,16 +208,16 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
pub(super) fn try_mutable_overloaded_place_op(
table: &InferenceTable<'db>,
krate: Crate,
base_ty: Ty<'db>,
opt_rhs_ty: Option<Ty<'db>>,
op: PlaceOp,
) -> Option<InferOk<'db, MethodCallee<'db>>> {
debug!("try_mutable_overloaded_place_op({:?},{:?})", base_ty, op);
let lang_items = table.interner().lang_items();
let (Some(mut_tr), mut_op) = (match op {
PlaceOp::Deref => (LangItem::DerefMut.resolve_trait(table.db, krate), sym::deref_mut),
PlaceOp::Index => (LangItem::IndexMut.resolve_trait(table.db, krate), sym::index_mut),
PlaceOp::Deref => (lang_items.DerefMut, sym::deref_mut),
PlaceOp::Index => (lang_items.IndexMut, sym::index_mut),
}) else {
// Bail if `DerefMut` or `IndexMut` isn't defined.
return None;
@ -276,8 +275,7 @@ impl<'a, 'db> InferenceContext<'a, 'db> {
))
}
};
let method =
Self::try_mutable_overloaded_place_op(&self.table, self.krate(), base_ty, arg_ty, op);
let method = Self::try_mutable_overloaded_place_op(&self.table, base_ty, arg_ty, op);
let method = match method {
Some(ok) => self.table.register_infer_ok(ok),
// Couldn't find the mutable variant of the place op, keep the

View file

@ -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<NextSolverError<'db>>,
) -> 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<TraitEnvironment<'db>>,
owner: Option<DefWithBodyId>,
) -> 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>>, 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(

View file

@ -1,6 +1,6 @@
//! Functions to detect special lang items
use hir_def::{AdtId, lang_item::LangItem, signatures::StructFlags};
use hir_def::{AdtId, TraitId, lang_item::LangItems, signatures::StructFlags};
use intern::{Symbol, sym};
use crate::db::HirDatabase;
@ -10,48 +10,51 @@ pub fn is_box(db: &dyn HirDatabase, adt: AdtId) -> bool {
db.struct_signature(id).flags.contains(StructFlags::IS_BOX)
}
pub fn lang_items_for_bin_op(op: syntax::ast::BinaryOp) -> Option<(Symbol, LangItem)> {
pub fn lang_items_for_bin_op(
lang_items: &LangItems,
op: syntax::ast::BinaryOp,
) -> Option<(Symbol, Option<TraitId>)> {
use syntax::ast::{ArithOp, BinaryOp, CmpOp, Ordering};
Some(match op {
BinaryOp::LogicOp(_) => return None,
BinaryOp::ArithOp(aop) => match aop {
ArithOp::Add => (sym::add, LangItem::Add),
ArithOp::Mul => (sym::mul, LangItem::Mul),
ArithOp::Sub => (sym::sub, LangItem::Sub),
ArithOp::Div => (sym::div, LangItem::Div),
ArithOp::Rem => (sym::rem, LangItem::Rem),
ArithOp::Shl => (sym::shl, LangItem::Shl),
ArithOp::Shr => (sym::shr, LangItem::Shr),
ArithOp::BitXor => (sym::bitxor, LangItem::BitXor),
ArithOp::BitOr => (sym::bitor, LangItem::BitOr),
ArithOp::BitAnd => (sym::bitand, LangItem::BitAnd),
ArithOp::Add => (sym::add, lang_items.Add),
ArithOp::Mul => (sym::mul, lang_items.Mul),
ArithOp::Sub => (sym::sub, lang_items.Sub),
ArithOp::Div => (sym::div, lang_items.Div),
ArithOp::Rem => (sym::rem, lang_items.Rem),
ArithOp::Shl => (sym::shl, lang_items.Shl),
ArithOp::Shr => (sym::shr, lang_items.Shr),
ArithOp::BitXor => (sym::bitxor, lang_items.BitXor),
ArithOp::BitOr => (sym::bitor, lang_items.BitOr),
ArithOp::BitAnd => (sym::bitand, lang_items.BitAnd),
},
BinaryOp::Assignment { op: Some(aop) } => match aop {
ArithOp::Add => (sym::add_assign, LangItem::AddAssign),
ArithOp::Mul => (sym::mul_assign, LangItem::MulAssign),
ArithOp::Sub => (sym::sub_assign, LangItem::SubAssign),
ArithOp::Div => (sym::div_assign, LangItem::DivAssign),
ArithOp::Rem => (sym::rem_assign, LangItem::RemAssign),
ArithOp::Shl => (sym::shl_assign, LangItem::ShlAssign),
ArithOp::Shr => (sym::shr_assign, LangItem::ShrAssign),
ArithOp::BitXor => (sym::bitxor_assign, LangItem::BitXorAssign),
ArithOp::BitOr => (sym::bitor_assign, LangItem::BitOrAssign),
ArithOp::BitAnd => (sym::bitand_assign, LangItem::BitAndAssign),
ArithOp::Add => (sym::add_assign, lang_items.AddAssign),
ArithOp::Mul => (sym::mul_assign, lang_items.MulAssign),
ArithOp::Sub => (sym::sub_assign, lang_items.SubAssign),
ArithOp::Div => (sym::div_assign, lang_items.DivAssign),
ArithOp::Rem => (sym::rem_assign, lang_items.RemAssign),
ArithOp::Shl => (sym::shl_assign, lang_items.ShlAssign),
ArithOp::Shr => (sym::shr_assign, lang_items.ShrAssign),
ArithOp::BitXor => (sym::bitxor_assign, lang_items.BitXorAssign),
ArithOp::BitOr => (sym::bitor_assign, lang_items.BitOrAssign),
ArithOp::BitAnd => (sym::bitand_assign, lang_items.BitAndAssign),
},
BinaryOp::CmpOp(cop) => match cop {
CmpOp::Eq { negated: false } => (sym::eq, LangItem::PartialEq),
CmpOp::Eq { negated: true } => (sym::ne, LangItem::PartialEq),
CmpOp::Eq { negated: false } => (sym::eq, lang_items.PartialEq),
CmpOp::Eq { negated: true } => (sym::ne, lang_items.PartialEq),
CmpOp::Ord { ordering: Ordering::Less, strict: false } => {
(sym::le, LangItem::PartialOrd)
(sym::le, lang_items.PartialOrd)
}
CmpOp::Ord { ordering: Ordering::Less, strict: true } => {
(sym::lt, LangItem::PartialOrd)
(sym::lt, lang_items.PartialOrd)
}
CmpOp::Ord { ordering: Ordering::Greater, strict: false } => {
(sym::ge, LangItem::PartialOrd)
(sym::ge, lang_items.PartialOrd)
}
CmpOp::Ord { ordering: Ordering::Greater, strict: true } => {
(sym::gt, LangItem::PartialOrd)
(sym::gt, lang_items.PartialOrd)
}
},
BinaryOp::Assignment { op: None } => return None,

View file

@ -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<TraitEnvironment<'db>>,
) -> Result<Arc<Layout>, 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 {

View file

@ -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,

View file

@ -477,14 +477,14 @@ pub fn callable_sig_from_fn_trait<'db>(
trait_env: Arc<TraitEnvironment<'db>>,
db: &'db dyn HirDatabase,
) -> Option<(FnTrait, PolyFnSig<'db>)> {
let krate = trait_env.krate;
let fn_once_trait = FnTrait::FnOnce.get_id(db, krate)?;
let mut table = InferenceTable::new(db, trait_env.clone(), None);
let lang_items = table.interner().lang_items();
let fn_once_trait = FnTrait::FnOnce.get_id(lang_items)?;
let output_assoc_type = fn_once_trait
.trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
let mut table = InferenceTable::new(db, trait_env.clone(), None);
// Register two obligations:
// - Self: FnOnce<?args_ty>
// - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
@ -502,7 +502,7 @@ pub fn callable_sig_from_fn_trait<'db>(
table.register_obligation(pred);
let return_ty = table.normalize_alias_ty(projection);
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
let fn_x_trait = fn_x.get_id(db, krate)?;
let fn_x_trait = fn_x.get_id(lang_items)?;
let trait_ref = TraitRef::new(table.interner(), fn_x_trait.into(), args);
if !table
.try_obligation(Predicate::upcast_from(trait_ref, table.interner()))

View file

@ -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<Item = Clause<'db>> + use<'b, 'a, 'db> {
let interner = self.interner;
let meta_sized = self.lang_items.MetaSized;
let pointee_sized = self.lang_items.PointeeSized;
let mut assoc_bounds = None;
let mut clause = None;
match bound {
@ -666,10 +669,6 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
if let Some((trait_ref, mut ctx)) = self.lower_trait_ref_from_path(path, self_ty) {
// FIXME(sized-hierarchy): Remove this bound modifications once we have implemented
// sized-hierarchy correctly.
let meta_sized = LangItem::MetaSized
.resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
let pointee_sized = LangItem::PointeeSized
.resolve_trait(ctx.ty_ctx().db, ctx.ty_ctx().resolver.krate());
if meta_sized.is_some_and(|it| it == trait_ref.def_id.0) {
// Ignore this bound
} else if pointee_sized.is_some_and(|it| it == trait_ref.def_id.0) {
@ -692,7 +691,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
}
&TypeBound::Path(path, TraitBoundModifier::Maybe) => {
let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate());
let sized_trait = self.lang_items.Sized;
// Don't lower associated type bindings as the only possible relaxed trait bound
// `?Sized` has no of them.
// If we got another trait here ignore the bound completely.
@ -873,12 +872,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
}
fn lower_impl_trait(
&mut self,
def_id: SolverDefId,
bounds: &[TypeBound],
krate: Crate,
) -> ImplTrait<'db> {
fn lower_impl_trait(&mut self, def_id: SolverDefId, bounds: &[TypeBound]) -> ImplTrait<'db> {
let interner = self.interner;
cov_mark::hit!(lower_rpit);
let args = GenericArgs::identity_for_item(interner, def_id);
@ -894,7 +888,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
if !ctx.unsized_types.contains(&self_ty) {
let sized_trait = LangItem::Sized.resolve_trait(self.db, krate);
let sized_trait = self.lang_items.Sized;
let sized_clause = sized_trait.map(|trait_id| {
let trait_ref = TraitRef::new_from_args(
interner,
@ -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<Name>,
) -> 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<TraitEnvironment<'db>> {
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<Clause<'db>>,
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<Ty<'db>>,
args: &'subst GenericArgs<'db>,
resolver: &Resolver<'db>,
) -> Option<impl Iterator<Item = Clause<'db>> + 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<TypeAliasId> {
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)
})

View file

@ -1100,7 +1100,7 @@ pub(crate) fn substs_from_args_and_bindings<'db>(
explicit_self_ty: Option<Ty<'db>>,
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);

View file

@ -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) => {

View file

@ -5,7 +5,6 @@ use hir_def::{
FunctionId, GenericDefId, GenericParamId, ItemContainerId, TraitId,
expr_store::path::{GenericArg as HirGenericArg, GenericArgs as HirGenericArgs},
hir::{ExprId, generics::GenericParamDataRef},
lang_item::LangItem,
};
use rustc_type_ir::{
TypeFoldable,
@ -550,9 +549,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
&self,
predicates: impl Iterator<Item = Clause<'db>>,
) -> bool {
let Some(sized_def_id) =
LangItem::Sized.resolve_trait(self.db(), self.ctx.resolver.krate())
else {
let Some(sized_def_id) = self.ctx.lang_items.Sized else {
return false;
};
@ -570,9 +567,7 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
fn check_for_illegal_method_calls(&self) {
// Disallow calls to the method `drop` defined in the `Drop` trait.
if let ItemContainerId::TraitId(trait_def_id) = self.candidate.loc(self.db()).container
&& LangItem::Drop
.resolve_trait(self.db(), self.ctx.resolver.krate())
.is_some_and(|drop_trait| drop_trait == trait_def_id)
&& self.ctx.lang_items.Drop.is_some_and(|drop_trait| drop_trait == trait_def_id)
{
// FIXME: Report an error.
}

View file

@ -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)
}

View file

@ -97,7 +97,7 @@ pub fn borrowck_query<'db>(
) -> Result<Arc<[BorrowckResult<'db>]>, 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)
}
}

View file

@ -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

View file

@ -3,7 +3,7 @@
//!
use std::cmp::{self, Ordering};
use hir_def::{CrateRootModuleId, resolver::HasResolver, signatures::FunctionSignature};
use hir_def::signatures::FunctionSignature;
use hir_expand::name::Name;
use intern::{Symbol, sym};
use rustc_type_ir::inherent::{AdtDef, IntoKind, SliceLike, Ty as _};
@ -14,8 +14,8 @@ use crate::{
drop::{DropGlue, has_drop_glue},
mir::eval::{
Address, AdtId, Arc, Evaluator, FunctionId, GenericArgs, HasModule, HirDisplay,
InternedClosure, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId, LangItem,
Layout, Locals, Lookup, MirEvalError, MirSpan, Mutability, Result, Ty, TyKind, pad16,
InternedClosure, Interval, IntervalAndTy, IntervalOrOwned, ItemContainerId, Layout, Locals,
Lookup, MirEvalError, MirSpan, Mutability, Result, Ty, TyKind, pad16,
},
next_solver::Region,
};
@ -38,6 +38,13 @@ macro_rules! not_supported {
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum EvalLangItem {
BeginPanic,
SliceLen,
DropInPlace,
}
impl<'db> Evaluator<'db> {
pub(super) fn detect_and_exec_special_function(
&mut self,
@ -105,7 +112,7 @@ impl<'db> Evaluator<'db> {
return Ok(true);
}
if let ItemContainerId::TraitId(t) = def.lookup(self.db).container
&& self.db.lang_attr(t.into()) == Some(LangItem::Clone)
&& Some(t) == self.lang_items().Clone
{
let [self_ty] = generic_args.as_slice() else {
not_supported!("wrong generic arg count for clone");
@ -131,12 +138,8 @@ impl<'db> Evaluator<'db> {
def: FunctionId,
) -> Result<'db, Option<FunctionId>> {
// `PanicFmt` is redirected to `ConstPanicFmt`
if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
let resolver = CrateRootModuleId::from(self.crate_id).resolver(self.db);
let Some(const_panic_fmt) =
LangItem::ConstPanicFmt.resolve_function(self.db, resolver.krate())
else {
if Some(def) == self.lang_items().PanicFmt {
let Some(const_panic_fmt) = self.lang_items().ConstPanicFmt else {
not_supported!("const_panic_fmt lang item not found or not a function");
};
return Ok(Some(const_panic_fmt));
@ -286,19 +289,26 @@ impl<'db> Evaluator<'db> {
Ok(())
}
fn detect_lang_function(&self, def: FunctionId) -> Option<LangItem> {
use LangItem::*;
fn detect_lang_function(&self, def: FunctionId) -> Option<EvalLangItem> {
use EvalLangItem::*;
let lang_items = self.lang_items();
let attrs = self.db.attrs(def.into());
if attrs.by_key(sym::rustc_const_panic_str).exists() {
// `#[rustc_const_panic_str]` is treated like `lang = "begin_panic"` by rustc CTFE.
return Some(LangItem::BeginPanic);
return Some(BeginPanic);
}
let candidate = attrs.lang_item()?;
// We want to execute these functions with special logic
// `PanicFmt` is not detected here as it's redirected later.
if [BeginPanic, SliceLen, DropInPlace].contains(&candidate) {
if let Some((_, candidate)) = [
(lang_items.BeginPanic, BeginPanic),
(lang_items.SliceLen, SliceLen),
(lang_items.DropInPlace, DropInPlace),
]
.iter()
.find(|&(candidate, _)| candidate == Some(def))
{
return Some(candidate);
}
@ -307,13 +317,13 @@ impl<'db> Evaluator<'db> {
fn exec_lang_item(
&mut self,
it: LangItem,
it: EvalLangItem,
generic_args: GenericArgs<'db>,
args: &[IntervalAndTy<'db>],
locals: &Locals<'db>,
span: MirSpan,
) -> Result<'db, Vec<u8>> {
use LangItem::*;
use EvalLangItem::*;
let mut args = args.iter();
match it {
BeginPanic => {
@ -374,7 +384,6 @@ impl<'db> Evaluator<'db> {
)?;
Ok(vec![])
}
it => not_supported!("Executing lang item {it:?}"),
}
}
@ -1219,7 +1228,7 @@ impl<'db> Evaluator<'db> {
let addr = tuple.interval.addr.offset(offset);
args.push(IntervalAndTy::new(addr, field, self, locals)?);
}
if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id)
if let Some(target) = self.lang_items().FnOnce
&& let Some(def) = target
.trait_items(self.db)
.method_by_name(&Name::new_symbol_root(sym::call_once))
@ -1329,7 +1338,7 @@ impl<'db> Evaluator<'db> {
{
result = (l as i8).cmp(&(r as i8));
}
if let Some(e) = LangItem::Ordering.resolve_enum(self.db, self.crate_id) {
if let Some(e) = self.lang_items().Ordering {
let ty = self.db.ty(e.into()).skip_binder();
let r = self.compute_discriminant(ty, &[result as i8 as u8])?;
destination.write_from_bytes(self, &r.to_le_bytes()[0..destination.size])?;

View file

@ -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;

View file

@ -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],

View file

@ -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(),

View file

@ -98,7 +98,7 @@ impl<'db> Filler<'db> {
env: Arc<TraitEnvironment<'db>>,
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 }
}

View file

@ -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;
};

View file

@ -8,9 +8,9 @@ pub use tls_db::{attach_db, attach_db_allow_change, with_attached_db};
use base_db::Crate;
use hir_def::{
AdtId, AttrDefId, BlockId, CallableDefId, DefWithBodyId, EnumVariantId, HasModule,
ItemContainerId, StructId, UnionId, VariantId,
lang_item::LangItem,
AdtId, BlockId, CallableDefId, DefWithBodyId, EnumVariantId, HasModule, ItemContainerId,
StructId, UnionId, VariantId,
lang_item::LangItems,
signatures::{FieldData, FnFlags, ImplFlags, StructFlags, TraitFlags},
};
use la_arena::Idx;
@ -272,6 +272,7 @@ pub struct DbInterner<'db> {
pub(crate) db: &'db dyn HirDatabase,
pub(crate) krate: Option<Crate>,
pub(crate) block: Option<BlockId>,
lang_items: Option<&'db LangItems>,
}
// FIXME: very wrong, see https://github.com/rust-lang/rust/pull/144808
@ -285,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<Crate>,
krate: Crate,
block: Option<BlockId>,
) -> 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<SolverLangItem> {
let def_id: AttrDefId = match def_id {
SolverDefId::TraitId(id) => id.into(),
SolverDefId::TypeAliasId(id) => id.into(),
SolverDefId::AdtId(id) => id.into(),
_ => panic!("Unexpected SolverDefId in as_lang_item"),
};
let lang_item = self.db().lang_attr(def_id)?;
as_lang_item!(
SolverLangItem, lang_item;
ignore = {
AsyncFnKindUpvars,
}
Metadata,
DynMetadata,
CoroutineReturn,
CoroutineYield,
FutureOutput,
CallRefFuture,
CallOnceFuture,
AsyncFnOnceOutput,
)
}
fn as_trait_lang_item(self, def_id: Self::TraitId) -> Option<SolverTraitLangItem> {
let def_id: AttrDefId = def_id.0.into();
let lang_item = self.db().lang_attr(def_id)?;
as_lang_item!(
SolverTraitLangItem, lang_item;
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<SolverLangItem> {
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<SolverTraitLangItem> {
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<SolverAdtLangItem> {
let def_id: AttrDefId = def_id.0.into();
let lang_item = self.db().lang_attr(def_id)?;
let AdtId::EnumId(def_id) = def_id.0 else {
panic!("Unexpected SolverDefId in as_adt_lang_item");
};
as_lang_item!(
SolverAdtLangItem, lang_item;
SolverAdtLangItem, self, def_id;
ignore = {}

View file

@ -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<Vec<Clause<'db>>> {
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.

View file

@ -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();

View file

@ -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);

View file

@ -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",

View file

@ -1,12 +1,11 @@
//! Trait solving using next trait solver.
use core::fmt;
use std::hash::Hash;
use base_db::Crate;
use hir_def::{
AdtId, AssocItemId, BlockId, HasModule, ImplId, Lookup, TraitId,
lang_item::LangItem,
lang_item::LangItems,
nameres::DefMap,
signatures::{ConstFlags, EnumFlags, FnFlags, StructFlags, TraitFlags, TypeAliasFlags},
};
@ -165,54 +164,7 @@ pub enum FnTrait {
AsyncFn,
}
impl fmt::Display for FnTrait {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FnTrait::FnOnce => write!(f, "FnOnce"),
FnTrait::FnMut => write!(f, "FnMut"),
FnTrait::Fn => write!(f, "Fn"),
FnTrait::AsyncFnOnce => write!(f, "AsyncFnOnce"),
FnTrait::AsyncFnMut => write!(f, "AsyncFnMut"),
FnTrait::AsyncFn => write!(f, "AsyncFn"),
}
}
}
impl FnTrait {
pub const fn function_name(&self) -> &'static str {
match self {
FnTrait::FnOnce => "call_once",
FnTrait::FnMut => "call_mut",
FnTrait::Fn => "call",
FnTrait::AsyncFnOnce => "async_call_once",
FnTrait::AsyncFnMut => "async_call_mut",
FnTrait::AsyncFn => "async_call",
}
}
const fn lang_item(self) -> LangItem {
match self {
FnTrait::FnOnce => LangItem::FnOnce,
FnTrait::FnMut => LangItem::FnMut,
FnTrait::Fn => LangItem::Fn,
FnTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
FnTrait::AsyncFnMut => LangItem::AsyncFnMut,
FnTrait::AsyncFn => LangItem::AsyncFn,
}
}
pub const fn from_lang_item(lang_item: LangItem) -> Option<Self> {
match lang_item {
LangItem::FnOnce => Some(FnTrait::FnOnce),
LangItem::FnMut => Some(FnTrait::FnMut),
LangItem::Fn => Some(FnTrait::Fn),
LangItem::AsyncFnOnce => Some(FnTrait::AsyncFnOnce),
LangItem::AsyncFnMut => Some(FnTrait::AsyncFnMut),
LangItem::AsyncFn => Some(FnTrait::AsyncFn),
_ => None,
}
}
pub fn method_name(self) -> Name {
match self {
FnTrait::FnOnce => Name::new_symbol_root(sym::call_once),
@ -224,8 +176,15 @@ impl FnTrait {
}
}
pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<TraitId> {
self.lang_item().resolve_trait(db, krate)
pub fn get_id(self, lang_items: &LangItems) -> Option<TraitId> {
match self {
FnTrait::FnOnce => lang_items.FnOnce,
FnTrait::FnMut => lang_items.FnMut,
FnTrait::Fn => lang_items.Fn,
FnTrait::AsyncFnOnce => lang_items.AsyncFnOnce,
FnTrait::AsyncFnMut => lang_items.AsyncFnMut,
FnTrait::AsyncFn => lang_items.AsyncFn,
}
}
}
@ -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());

View file

@ -3,15 +3,12 @@
use std::cell::LazyCell;
use base_db::{
Crate,
target::{self, TargetData},
};
use base_db::target::{self, TargetData};
use hir_def::{
EnumId, EnumVariantId, FunctionId, Lookup, TraitId,
db::DefDatabase,
hir::generics::WherePredicate,
lang_item::LangItem,
lang_item::LangItems,
resolver::{HasResolver, TypeNs},
type_ref::{TraitBoundModifier, TypeRef},
};
@ -27,10 +24,8 @@ use crate::{
mir::pad16,
};
pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator<Item = TraitId> + '_ {
[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce]
.into_iter()
.filter_map(move |lang| lang.resolve_trait(db, krate))
pub(crate) fn fn_traits(lang_items: &LangItems) -> impl Iterator<Item = TraitId> + '_ {
[lang_items.Fn, lang_items.FnMut, lang_items.FnOnce].into_iter().flatten()
}
/// Returns an iterator over the direct super traits (including the trait itself).

View file

@ -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();

View file

@ -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());

View file

@ -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,

View file

@ -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<Layout, LayoutError> {
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<Item = Type<'db>>,
) -> 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<Item = Type<'db>>,
) -> 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<Item = Type<'db>>,
) -> Vec<Param<'db>> {
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<String, ConstEvalError<'_>> {
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<Item = Type<'db>>,
) -> 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<EvaluatedConst<'_>, 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<Trait> {
LangItem::from_name(name)?.resolve_trait(db, krate.into()).map(Into::into)
pub fn lang(db: &dyn HirDatabase, krate: Crate, lang_item: LangItem) -> Option<Trait> {
let lang_items = hir_def::lang_item::lang_items(db, krate.id);
match lang_item.from_lang_items(lang_items)? {
LangItemTarget::TraitId(it) => Some(it.into()),
_ => None,
}
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
@ -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<Impl> {
pub fn all_for_type<'db>(
db: &'db dyn HirDatabase,
Type { ty, env: _ }: Type<'db>,
) -> Vec<Impl> {
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<traits::FnTrait> for FnTrait {
fn from(value: traits::FnTrait) -> Self {
match value {
traits::FnTrait::FnOnce => FnTrait::FnOnce,
traits::FnTrait::FnMut => FnTrait::FnMut,
traits::FnTrait::Fn => FnTrait::Fn,
traits::FnTrait::AsyncFnOnce => FnTrait::AsyncFnOnce,
traits::FnTrait::AsyncFnMut => FnTrait::AsyncFnMut,
traits::FnTrait::AsyncFn => FnTrait::AsyncFn,
}
}
}
impl fmt::Display for FnTrait {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FnTrait::FnOnce => write!(f, "FnOnce"),
FnTrait::FnMut => write!(f, "FnMut"),
FnTrait::Fn => write!(f, "Fn"),
FnTrait::AsyncFnOnce => write!(f, "AsyncFnOnce"),
FnTrait::AsyncFnMut => write!(f, "AsyncFnMut"),
FnTrait::AsyncFn => write!(f, "AsyncFn"),
}
}
}
impl FnTrait {
pub const fn function_name(&self) -> &'static str {
match self {
FnTrait::FnOnce => "call_once",
FnTrait::FnMut => "call_mut",
FnTrait::Fn => "call",
FnTrait::AsyncFnOnce => "async_call_once",
FnTrait::AsyncFnMut => "async_call_mut",
FnTrait::AsyncFn => "async_call",
}
}
pub fn lang_item(self) -> LangItem {
match self {
FnTrait::FnOnce => LangItem::FnOnce,
FnTrait::FnMut => LangItem::FnMut,
FnTrait::Fn => LangItem::Fn,
FnTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
FnTrait::AsyncFnMut => LangItem::AsyncFnMut,
FnTrait::AsyncFn => LangItem::AsyncFn,
}
}
pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<Trait> {
Trait::lang(db, krate, self.lang_item())
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClosureCapture<'db> {
owner: DefWithBodyId,
@ -4821,7 +4891,7 @@ impl<'db> Type<'db> {
}
fn from_def(db: &'db dyn HirDatabase, def: impl Into<TyDefId> + 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<ValueTyDefId> + 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<Type<'db>> {
let trait_ = LangItem::IntoFutureIntoFuture
.resolve_function(db, self.env.krate)
let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
let trait_ = lang_items
.IntoFutureIntoFuture
.and_then(|into_future_fn| {
let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
let into_future_trait = assoc_item.container_or_implemented_trait(db)?;
Some(into_future_trait.id)
})
.or_else(|| LangItem::Future.resolve_trait(db, self.env.krate))?;
.or(lang_items.Future)?;
if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
return None;
@ -5072,13 +5143,15 @@ impl<'db> Type<'db> {
/// This does **not** resolve `IntoFuture`, only `Future`.
pub fn future_output(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
let future_output = LangItem::FutureOutput.resolve_type_alias(db, self.env.krate)?;
let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
let future_output = lang_items.FutureOutput?;
self.normalize_trait_assoc_type(db, &[], future_output.into())
}
/// This does **not** resolve `IntoIterator`, only `Iterator`.
pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
let iterator_trait = lang_items.Iterator?;
let iterator_item = iterator_trait
.trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
@ -5086,7 +5159,8 @@ impl<'db> Type<'db> {
}
pub fn impls_iterator(self, db: &'db dyn HirDatabase) -> bool {
let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else {
let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
let Some(iterator_trait) = lang_items.Iterator else {
return false;
};
traits::implements_trait_unique(self.ty, db, self.env.clone(), iterator_trait)
@ -5094,13 +5168,12 @@ impl<'db> Type<'db> {
/// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
let trait_ = LangItem::IntoIterIntoIter.resolve_function(db, self.env.krate).and_then(
|into_iter_fn| {
let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
Some(into_iter_trait.id)
},
)?;
let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
let trait_ = lang_items.IntoIterIntoIter.and_then(|into_iter_fn| {
let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
Some(into_iter_trait.id)
})?;
if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
return None;
@ -5117,7 +5190,8 @@ impl<'db> Type<'db> {
/// This function can be used to check if a particular type is callable, since FnOnce is a
/// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
pub fn impls_fnonce(&self, db: &'db dyn HirDatabase) -> bool {
let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) {
let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
let fnonce_trait = match lang_items.FnOnce {
Some(it) => it,
None => return false,
};
@ -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<Type<'db>> {
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<Callable<'db>> {
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<Item = Ty<'db>> {
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<T>` and `Option<U>` 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<T>` and `Option<U>` 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>)> {

View file

@ -1655,7 +1655,7 @@ impl<'db> SemanticsImpl<'db> {
func: Function,
subst: impl IntoIterator<Item = Type<'db>>,
) -> Option<Function> {
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, _| {

View file

@ -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<Type<'db>> {
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<Callable<'db>> {
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<FunctionId> {
let ty = self.ty_of_expr(try_expr.expr()?)?;
let op_fn = LangItem::TryTraitBranch.resolve_function(db, self.resolver.krate())?;
let op_fn = self.lang_items(db).TryTraitBranch?;
// HACK: subst for `branch()` coincides with that for `Try` because `branch()` itself
// doesn't have any generic parameters, so we skip building another subst for `branch()`.
let interner = DbInterner::new_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<LocalFieldId>,
) -> 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<TraitId>,
method_name: &Name,
) -> Option<(TraitId, FunctionId)> {
let trait_id = lang_trait.resolve_trait(db, self.resolver.krate())?;
let trait_id = lang_trait?;
let fn_id = trait_id.trait_items(db).method_by_name(method_name)?;
Some((trait_id, fn_id))
}

View file

@ -597,7 +597,7 @@ pub(super) fn famous_types<'a, 'lt, 'db, DB: HirDatabase>(
) -> impl Iterator<Item = Expr<'db>> + 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);
[

View file

@ -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());

View file

@ -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());

View file

@ -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
"#]],
);
}

View file

@ -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()));
}
});

View file

@ -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,

View file

@ -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()