Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
-rw-r--r--crates/hir/src/lib.rs127
1 files changed, 101 insertions, 26 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index f941cbd232..4c21b98066 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -59,6 +59,7 @@ use hir_def::{
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
},
item_tree::ImportAlias,
+ lang_item::LangItemTarget,
layout::{self, ReprOptions, TargetDataLayout},
nameres::{
assoc::TraitItems,
@@ -91,7 +92,7 @@ use hir_ty::{
PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode,
infer::{DbInternerInferExt, InferCtxt},
},
- traits::{self, FnTrait, is_inherent_impl_coherent, structurally_normalize_ty},
+ traits::{self, is_inherent_impl_coherent, structurally_normalize_ty},
};
use itertools::Itertools;
use rustc_hash::FxHashSet;
@@ -138,7 +139,7 @@ pub use {
attr::{AttrSourceMap, Attrs, AttrsWithOwner},
find_path::PrefixKind,
import_map,
- lang_item::{LangItem, crate_lang_items},
+ lang_item::{LangItemEnum as LangItem, crate_lang_items},
nameres::{DefMap, ModuleSource, crate_def_map},
per_ns::Namespace,
type_ref::{Mutability, TypeRef},
@@ -818,7 +819,7 @@ impl Module {
let drop_maybe_dangle = (|| {
// FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper
let trait_ = trait_?;
- let drop_trait = LangItem::Drop.resolve_trait(db, self.krate().into())?;
+ let drop_trait = interner.lang_items().Drop?;
if drop_trait != trait_.into() {
return None;
}
@@ -2436,11 +2437,11 @@ impl Function {
let ret_type = self.ret_type(db);
let Some(impl_traits) = ret_type.as_impl_traits(db) else { return false };
- let Some(future_trait_id) = LangItem::Future.resolve_trait(db, self.ty(db).env.krate)
- else {
+ let lang_items = hir_def::lang_item::lang_items(db, self.krate(db).id);
+ let Some(future_trait_id) = lang_items.Future else {
return false;
};
- let Some(sized_trait_id) = LangItem::Sized.resolve_trait(db, self.ty(db).env.krate) else {
+ let Some(sized_trait_id) = lang_items.Sized else {
return false;
};
@@ -2905,8 +2906,12 @@ pub struct Trait {
}
impl Trait {
- pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
- LangItem::from_name(name)?.resolve_trait(db, krate.into()).map(Into::into)
+ pub fn lang(db: &dyn HirDatabase, krate: Crate, lang_item: LangItem) -> Option<Trait> {
+ let lang_items = hir_def::lang_item::lang_items(db, krate.id);
+ match lang_item.from_lang_items(lang_items)? {
+ LangItemTarget::TraitId(it) => Some(it.into()),
+ _ => None,
+ }
}
pub fn module(self, db: &dyn HirDatabase) -> Module {
@@ -4650,7 +4655,7 @@ impl<'db> Closure<'db> {
let owner = db.lookup_intern_closure(id).0;
let infer = db.infer(owner);
let info = infer.closure_info(id);
- info.1
+ info.1.into()
}
AnyClosureId::CoroutineClosureId(_id) => {
// FIXME: Infer kind for coroutine closures.
@@ -4664,6 +4669,71 @@ impl<'db> Closure<'db> {
}
}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum FnTrait {
+ FnOnce,
+ FnMut,
+ Fn,
+
+ AsyncFnOnce,
+ AsyncFnMut,
+ AsyncFn,
+}
+
+impl From<traits::FnTrait> for FnTrait {
+ fn from(value: traits::FnTrait) -> Self {
+ match value {
+ traits::FnTrait::FnOnce => FnTrait::FnOnce,
+ traits::FnTrait::FnMut => FnTrait::FnMut,
+ traits::FnTrait::Fn => FnTrait::Fn,
+ traits::FnTrait::AsyncFnOnce => FnTrait::AsyncFnOnce,
+ traits::FnTrait::AsyncFnMut => FnTrait::AsyncFnMut,
+ traits::FnTrait::AsyncFn => FnTrait::AsyncFn,
+ }
+ }
+}
+
+impl fmt::Display for FnTrait {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ FnTrait::FnOnce => write!(f, "FnOnce"),
+ FnTrait::FnMut => write!(f, "FnMut"),
+ FnTrait::Fn => write!(f, "Fn"),
+ FnTrait::AsyncFnOnce => write!(f, "AsyncFnOnce"),
+ FnTrait::AsyncFnMut => write!(f, "AsyncFnMut"),
+ FnTrait::AsyncFn => write!(f, "AsyncFn"),
+ }
+ }
+}
+
+impl FnTrait {
+ pub const fn function_name(&self) -> &'static str {
+ match self {
+ FnTrait::FnOnce => "call_once",
+ FnTrait::FnMut => "call_mut",
+ FnTrait::Fn => "call",
+ FnTrait::AsyncFnOnce => "async_call_once",
+ FnTrait::AsyncFnMut => "async_call_mut",
+ FnTrait::AsyncFn => "async_call",
+ }
+ }
+
+ pub fn lang_item(self) -> LangItem {
+ match self {
+ FnTrait::FnOnce => LangItem::FnOnce,
+ FnTrait::FnMut => LangItem::FnMut,
+ FnTrait::Fn => LangItem::Fn,
+ FnTrait::AsyncFnOnce => LangItem::AsyncFnOnce,
+ FnTrait::AsyncFnMut => LangItem::AsyncFnMut,
+ FnTrait::AsyncFn => LangItem::AsyncFn,
+ }
+ }
+
+ pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<Trait> {
+ Trait::lang(db, krate, self.lang_item())
+ }
+}
+
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClosureCapture<'db> {
owner: DefWithBodyId,
@@ -5052,14 +5122,15 @@ impl<'db> Type<'db> {
/// `std::future::Future` and returns the `Output` associated type.
/// This function is used in `.await` syntax completion.
pub fn into_future_output(&self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let trait_ = LangItem::IntoFutureIntoFuture
- .resolve_function(db, self.env.krate)
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let trait_ = lang_items
+ .IntoFutureIntoFuture
.and_then(|into_future_fn| {
let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
let into_future_trait = assoc_item.container_or_implemented_trait(db)?;
Some(into_future_trait.id)
})
- .or_else(|| LangItem::Future.resolve_trait(db, self.env.krate))?;
+ .or(lang_items.Future)?;
if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
return None;
@@ -5072,13 +5143,15 @@ impl<'db> Type<'db> {
/// This does **not** resolve `IntoFuture`, only `Future`.
pub fn future_output(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let future_output = LangItem::FutureOutput.resolve_type_alias(db, self.env.krate)?;
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let future_output = lang_items.FutureOutput?;
self.normalize_trait_assoc_type(db, &[], future_output.into())
}
/// This does **not** resolve `IntoIterator`, only `Iterator`.
pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let iterator_trait = lang_items.Iterator?;
let iterator_item = iterator_trait
.trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
@@ -5086,7 +5159,8 @@ impl<'db> Type<'db> {
}
pub fn impls_iterator(self, db: &'db dyn HirDatabase) -> bool {
- let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else {
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let Some(iterator_trait) = lang_items.Iterator else {
return false;
};
traits::implements_trait_unique(self.ty, db, self.env.clone(), iterator_trait)
@@ -5094,13 +5168,12 @@ impl<'db> Type<'db> {
/// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
- let trait_ = LangItem::IntoIterIntoIter.resolve_function(db, self.env.krate).and_then(
- |into_iter_fn| {
- let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
- let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
- Some(into_iter_trait.id)
- },
- )?;
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let trait_ = lang_items.IntoIterIntoIter.and_then(|into_iter_fn| {
+ let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
+ let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
+ Some(into_iter_trait.id)
+ })?;
if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
return None;
@@ -5117,7 +5190,8 @@ impl<'db> Type<'db> {
/// This function can be used to check if a particular type is callable, since FnOnce is a
/// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
pub fn impls_fnonce(&self, db: &'db dyn HirDatabase) -> bool {
- let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) {
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let fnonce_trait = match lang_items.FnOnce {
Some(it) => it,
None => return false,
};
@@ -5161,7 +5235,8 @@ impl<'db> Type<'db> {
}
pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool {
- let Some(copy_trait) = LangItem::Copy.resolve_trait(db, self.env.krate) else {
+ let lang_items = hir_def::lang_item::lang_items(db, self.env.krate);
+ let Some(copy_trait) = lang_items.Copy else {
return false;
};
self.impls_trait(db, copy_trait.into(), &[])
@@ -5913,7 +5988,7 @@ enum Callee<'db> {
Closure(InternedClosureId, GenericArgs<'db>),
CoroutineClosure(InternedCoroutineId, GenericArgs<'db>),
FnPtr,
- FnImpl(FnTrait),
+ FnImpl(traits::FnTrait),
}
pub enum CallableKind<'db> {
@@ -5940,7 +6015,7 @@ impl<'db> Callable<'db> {
CallableKind::Closure(Closure { id: AnyClosureId::CoroutineClosureId(id), subst })
}
Callee::FnPtr => CallableKind::FnPtr,
- Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_),
+ Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_.into()),
}
}
pub fn receiver_param(&self, db: &'db dyn HirDatabase) -> Option<(SelfParam, Type<'db>)> {