refactor: De-arc lang item queries

This commit is contained in:
Lukas Wirth 2025-04-28 17:16:28 +02:00
parent 5adee2ad2c
commit 6355df9c57
23 changed files with 194 additions and 261 deletions

View file

@ -198,15 +198,13 @@ pub(crate) fn deref_by_trait(
// blanked impl on `Deref`.
#[expect(clippy::overly_complex_bool_expr)]
if use_receiver_trait && false {
if let Some(receiver) =
db.lang_item(table.trait_env.krate, LangItem::Receiver).and_then(|l| l.as_trait())
{
if let Some(receiver) = LangItem::Receiver.resolve_trait(db, table.trait_env.krate) {
return Some(receiver);
}
}
// Old rustc versions might not have `Receiver` trait.
// Fallback to `Deref` if they don't
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())
LangItem::Deref.resolve_trait(db, table.trait_env.krate)
};
let trait_id = trait_id()?;
let target =

View file

@ -16,7 +16,7 @@ use hir_def::{
AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup,
TypeAliasId, VariantId,
hir::Movability,
lang_item::{LangItem, LangItemTarget},
lang_item::LangItem,
signatures::{ImplFlags, StructFlags, TraitFlags},
};
@ -262,10 +262,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
well_known_trait: rust_ir::WellKnownTrait,
) -> Option<chalk_ir::TraitId<Interner>> {
let lang_attr = lang_item_from_well_known_trait(well_known_trait);
let trait_ = match self.db.lang_item(self.krate, lang_attr) {
Some(LangItemTarget::Trait(trait_)) => trait_,
_ => return None,
};
let trait_ = lang_attr.resolve_trait(self.db, self.krate)?;
Some(to_chalk_trait_id(trait_))
}
@ -306,11 +303,8 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
chalk_ir::Binders::new(binders, bound)
}
crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
if let Some((future_trait, future_output)) = self
.db
.lang_item(self.krate, LangItem::Future)
.and_then(|item| item.as_trait())
.and_then(|trait_| {
if let Some((future_trait, future_output)) =
LangItem::Future.resolve_trait(self.db, self.krate).and_then(|trait_| {
let alias = self
.db
.trait_items(trait_)
@ -338,10 +332,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
});
let mut binder = vec![];
binder.push(crate::wrap_empty_binders(impl_bound));
let sized_trait = self
.db
.lang_item(self.krate, LangItem::Sized)
.and_then(|item| item.as_trait());
let sized_trait = LangItem::Sized.resolve_trait(self.db, self.krate);
if let Some(sized_trait_) = sized_trait {
let sized_bound = WhereClause::Implemented(TraitRef {
trait_id: to_chalk_trait_id(sized_trait_),
@ -660,9 +651,8 @@ pub(crate) fn associated_ty_data_query(
}
if !ctx.unsized_types.contains(&self_ty) {
let sized_trait = db
.lang_item(resolver.krate(), LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
let sized_trait =
LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id);
let sized_bound = sized_trait.into_iter().map(|sized_trait| {
let trait_bound =
rust_ir::TraitBound { trait_id: sized_trait, args_no_self: Default::default() };

View file

@ -251,9 +251,7 @@ impl TyExt for Ty {
match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
let krate = def.module(db).krate();
if let Some(future_trait) =
db.lang_item(krate, LangItem::Future).and_then(|item| item.as_trait())
{
if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
// This is only used by type walking.
// Parameters will be walked outside, and projection predicate is not used.
// So just provide the Future trait.
@ -364,8 +362,7 @@ impl TyExt for Ty {
fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool {
let crate_id = owner.module(db).krate();
let Some(copy_trait) = db.lang_item(crate_id, LangItem::Copy).and_then(|it| it.as_trait())
else {
let Some(copy_trait) = LangItem::Copy.resolve_trait(db, crate_id) else {
return false;
};
let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(self).build();

View file

@ -482,9 +482,8 @@ struct FilterMapNextChecker {
impl FilterMapNextChecker {
fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self {
// Find and store the FunctionIds for Iterator::filter_map and Iterator::next
let (next_function_id, filter_map_function_id) = match db
.lang_item(resolver.krate(), LangItem::IteratorNext)
.and_then(|it| it.as_function())
let (next_function_id, filter_map_function_id) = match LangItem::IteratorNext
.resolve_function(db, resolver.krate())
{
Some(next_function_id) => (
Some(next_function_id),

View file

@ -19,7 +19,7 @@ use hir_def::{
hir::generics::{TypeOrConstParamData, TypeParamProvenance, WherePredicate},
item_scope::ItemInNs,
item_tree::FieldsShape,
lang_item::{LangItem, LangItemTarget},
lang_item::LangItem,
nameres::DefMap,
signatures::VariantFields,
type_ref::{
@ -1348,9 +1348,8 @@ impl HirDisplay for Ty {
)?;
}
ImplTraitId::AsyncBlockTypeImplTrait(body, ..) => {
let future_trait = db
.lang_item(body.module(db).krate(), LangItem::Future)
.and_then(LangItemTarget::as_trait);
let future_trait =
LangItem::Future.resolve_trait(db, body.module(db).krate());
let output = future_trait.and_then(|t| {
db.trait_items(t)
.associated_type_by_name(&Name::new_symbol_root(sym::Output))
@ -1728,9 +1727,7 @@ impl SizedByDefault {
match self {
Self::NotSized => false,
Self::Sized { anchor } => {
let sized_trait = db
.lang_item(anchor, LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait());
let sized_trait = LangItem::Sized.resolve_trait(db, anchor);
Some(trait_) == sized_trait
}
}
@ -1895,8 +1892,7 @@ fn write_bounds_like_dyn_trait(
write!(f, ">")?;
}
if let SizedByDefault::Sized { anchor } = default_sized {
let sized_trait =
f.db.lang_item(anchor, LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
let sized_trait = LangItem::Sized.resolve_trait(f.db, anchor);
if !is_sized {
if !first {
write!(f, " + ")?;

View file

@ -19,9 +19,7 @@ fn has_destructor(db: &dyn HirDatabase, adt: AdtId) -> bool {
AdtId::StructId(id) => db.lookup_intern_struct(id).container,
AdtId::UnionId(id) => db.lookup_intern_union(id).container,
};
let Some(drop_trait) =
db.lang_item(module.krate(), LangItem::Drop).and_then(|it| it.as_trait())
else {
let Some(drop_trait) = LangItem::Drop.resolve_trait(db, module.krate()) else {
return false;
};
let impls = match module.containing_block() {
@ -181,8 +179,7 @@ fn projection_has_drop_glue(
}
fn is_copy(db: &dyn HirDatabase, ty: Ty, env: Arc<TraitEnvironment>) -> bool {
let Some(copy_trait) = db.lang_item(env.krate, LangItem::Copy).and_then(|it| it.as_trait())
else {
let Some(copy_trait) = LangItem::Copy.resolve_trait(db, env.krate) else {
return false;
};
let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(ty).build();

View file

@ -124,7 +124,7 @@ pub fn dyn_compatibility_of_trait_query(
fn generics_require_sized_self(db: &dyn HirDatabase, def: GenericDefId) -> bool {
let krate = def.module(db).krate();
let Some(sized) = db.lang_item(krate, LangItem::Sized).and_then(|l| l.as_trait()) else {
let Some(sized) = LangItem::Sized.resolve_trait(db, krate) else {
return false;
};
@ -491,8 +491,8 @@ fn receiver_is_dispatchable(
let krate = func.module(db).krate();
let traits = (
db.lang_item(krate, LangItem::Unsize).and_then(|it| it.as_trait()),
db.lang_item(krate, LangItem::DispatchFromDyn).and_then(|it| it.as_trait()),
LangItem::Unsize.resolve_trait(db, krate),
LangItem::DispatchFromDyn.resolve_trait(db, krate),
);
let (Some(unsize_did), Some(dispatch_from_dyn_did)) = traits else {
return false;

View file

@ -39,7 +39,7 @@ use hir_def::{
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
expr_store::{Body, ExpressionStore, HygieneId, path::Path},
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
lang_item::{LangItem, LangItemTarget},
lang_item::{LangItem, LangItemTarget, lang_item},
layout::Integer,
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
signatures::{ConstSignature, StaticSignature},
@ -1801,7 +1801,7 @@ impl<'a> InferenceContext<'a> {
fn resolve_lang_item(&self, item: LangItem) -> Option<LangItemTarget> {
let krate = self.resolver.krate();
self.db.lang_item(krate, item)
lang_item(self.db, krate, item)
}
fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {

View file

@ -8,10 +8,7 @@
use std::iter;
use chalk_ir::{BoundVar, Goal, Mutability, TyKind, TyVariableKind, cast::Cast};
use hir_def::{
hir::ExprId,
lang_item::{LangItem, LangItemTarget},
};
use hir_def::{hir::ExprId, lang_item::LangItem};
use stdx::always;
use triomphe::Arc;
@ -701,8 +698,8 @@ impl InferenceTable<'_> {
reborrow.as_ref().map_or_else(|| from_ty.clone(), |(_, adj)| adj.target.clone());
let krate = self.trait_env.krate;
let coerce_unsized_trait = match self.db.lang_item(krate, LangItem::CoerceUnsized) {
Some(LangItemTarget::Trait(trait_)) => trait_,
let coerce_unsized_trait = match LangItem::CoerceUnsized.resolve_trait(self.db, krate) {
Some(trait_) => trait_,
_ => return Err(TypeError),
};

View file

@ -126,10 +126,8 @@ impl InferenceContext<'_> {
&Expr::Index { base, index } => {
if mutability == Mutability::Mut {
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
if let Some(index_trait) = self
.db
.lang_item(self.table.trait_env.krate, LangItem::IndexMut)
.and_then(|l| l.as_trait())
if let Some(index_trait) =
LangItem::IndexMut.resolve_trait(self.db, self.table.trait_env.krate)
{
if let Some(index_fn) = self
.db
@ -183,10 +181,8 @@ impl InferenceContext<'_> {
let mut mutability = mutability;
if let Some((f, _)) = self.result.method_resolutions.get_mut(&tgt_expr) {
if mutability == Mutability::Mut {
if let Some(deref_trait) = self
.db
.lang_item(self.table.trait_env.krate, LangItem::DerefMut)
.and_then(|l| l.as_trait())
if let Some(deref_trait) =
LangItem::DerefMut.resolve_trait(self.db, self.table.trait_env.krate)
{
let ty = self.result.type_of_expr.get(*expr);
let is_mut_ptr = ty.is_some_and(|ty| {

View file

@ -1024,11 +1024,7 @@ impl<'a> InferenceTable<'a> {
}
}
let Some(sized) = self
.db
.lang_item(self.trait_env.krate, LangItem::Sized)
.and_then(|sized| sized.as_trait())
else {
let Some(sized) = LangItem::Sized.resolve_trait(self.db, self.trait_env.krate) else {
return false;
};
let sized_pred = WhereClause::Implemented(TraitRef {

View file

@ -590,10 +590,7 @@ impl<'a> TyLoweringContext<'a> {
}
}
&TypeBound::Path(path, TraitBoundModifier::Maybe) => {
let sized_trait = self
.db
.lang_item(self.resolver.krate(), LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait());
let sized_trait = LangItem::Sized.resolve_trait(self.db, self.resolver.krate());
// Don't lower associated type bindings as the only possible relaxed trait bound
// `?Sized` has no of them.
// If we got another trait here ignore the bound completely.
@ -736,10 +733,8 @@ impl<'a> TyLoweringContext<'a> {
}
if !ctx.unsized_types.contains(&self_ty) {
let sized_trait = ctx
.db
.lang_item(krate, LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
let sized_trait =
LangItem::Sized.resolve_trait(ctx.db, krate).map(to_chalk_trait_id);
let sized_clause = sized_trait.map(|trait_id| {
let clause = WhereClause::Implemented(TraitRef {
trait_id,
@ -1188,9 +1183,7 @@ fn implicitly_sized_clauses<'a, 'subst: 'a>(
substitution: &'subst Substitution,
resolver: &Resolver,
) -> Option<impl Iterator<Item = WhereClause> + Captures<'a> + Captures<'subst>> {
let sized_trait = db
.lang_item(resolver.krate(), LangItem::Sized)
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id))?;
let sized_trait = LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id)?;
let trait_self_idx = trait_self_param_idx(db, def);

View file

@ -655,22 +655,15 @@ impl Evaluator<'_> {
mir_or_dyn_index_cache: RefCell::new(Default::default()),
unused_locals_store: RefCell::new(Default::default()),
cached_ptr_size,
cached_fn_trait_func: db
.lang_item(crate_id, LangItem::Fn)
.and_then(|x| x.as_trait())
cached_fn_trait_func: LangItem::Fn
.resolve_trait(db, crate_id)
.and_then(|x| db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call))),
cached_fn_mut_trait_func: db
.lang_item(crate_id, LangItem::FnMut)
.and_then(|x| x.as_trait())
.and_then(|x| {
db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut))
}),
cached_fn_once_trait_func: db
.lang_item(crate_id, LangItem::FnOnce)
.and_then(|x| x.as_trait())
.and_then(|x| {
db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once))
}),
cached_fn_mut_trait_func: LangItem::FnMut.resolve_trait(db, crate_id).and_then(|x| {
db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_mut))
}),
cached_fn_once_trait_func: LangItem::FnOnce.resolve_trait(db, crate_id).and_then(|x| {
db.trait_items(x).method_by_name(&Name::new_symbol_root(sym::call_once))
}),
})
}
@ -2811,7 +2804,7 @@ impl Evaluator<'_> {
span: MirSpan,
) -> Result<()> {
let Some(drop_fn) = (|| {
let drop_trait = self.db.lang_item(self.crate_id, LangItem::Drop)?.as_trait()?;
let drop_trait = LangItem::Drop.resolve_trait(self.db, self.crate_id)?;
self.db.trait_items(drop_trait).method_by_name(&Name::new_symbol_root(sym::drop))
})() else {
// in some tests we don't have drop trait in minicore, and

View file

@ -6,7 +6,6 @@ use std::cmp::{self, Ordering};
use chalk_ir::TyKind;
use hir_def::{
builtin_type::{BuiltinInt, BuiltinUint},
lang_item::LangItemTarget,
resolver::HasResolver,
};
use hir_expand::name::Name;
@ -156,8 +155,8 @@ impl Evaluator<'_> {
if let Some(LangItem::PanicFmt) = self.db.lang_attr(def.into()) {
let resolver = self.db.crate_def_map(self.crate_id).crate_root().resolver(self.db);
let Some(hir_def::lang_item::LangItemTarget::Function(const_panic_fmt)) =
self.db.lang_item(resolver.krate(), LangItem::ConstPanicFmt)
let Some(const_panic_fmt) =
LangItem::ConstPanicFmt.resolve_function(self.db, resolver.krate())
else {
not_supported!("const_panic_fmt lang item not found or not a function");
};
@ -1257,12 +1256,12 @@ impl Evaluator<'_> {
let addr = tuple.interval.addr.offset(offset);
args.push(IntervalAndTy::new(addr, field, self, locals)?);
}
if let Some(target) = self.db.lang_item(self.crate_id, LangItem::FnOnce) {
if let Some(def) = target.as_trait().and_then(|it| {
self.db
.trait_items(it)
.method_by_name(&Name::new_symbol_root(sym::call_once))
}) {
if let Some(target) = LangItem::FnOnce.resolve_trait(self.db, self.crate_id) {
if let Some(def) = self
.db
.trait_items(target)
.method_by_name(&Name::new_symbol_root(sym::call_once))
{
self.exec_fn_trait(
def,
&args,
@ -1376,9 +1375,7 @@ impl Evaluator<'_> {
}
}
}
if let Some(LangItemTarget::EnumId(e)) =
self.db.lang_item(self.crate_id, LangItem::Ordering)
{
if let Some(e) = LangItem::Ordering.resolve_enum(self.db, self.crate_id) {
let ty = self.db.ty(e.into());
let r = self
.compute_discriminant(ty.skip_binders().clone(), &[result as i8 as u8])?;

View file

@ -13,7 +13,7 @@ use hir_def::{
Pat, PatId, RecordFieldPat, RecordLitField,
},
item_tree::FieldsShape,
lang_item::{LangItem, LangItemTarget},
lang_item::{LangItem, LangItemTarget, lang_item},
resolver::{HasResolver, ResolveValueResult, Resolver, ValueNs},
};
use hir_expand::name::Name;
@ -1727,7 +1727,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
fn resolve_lang_item(&self, item: LangItem) -> Result<LangItemTarget> {
let crate_id = self.owner.module(self.db).krate();
self.db.lang_item(crate_id, item).ok_or(MirLowerError::LangItemNotFound(item))
lang_item(self.db, crate_id, item).ok_or(MirLowerError::LangItemNotFound(item))
}
fn lower_block_to_place(

View file

@ -8,10 +8,7 @@ use chalk_recursive::Cache;
use chalk_solve::{Solver, logging_db::LoggingRustIrDatabase, rust_ir};
use base_db::Crate;
use hir_def::{
BlockId, TraitId,
lang_item::{LangItem, LangItemTarget},
};
use hir_def::{BlockId, TraitId, lang_item::LangItem};
use hir_expand::name::Name;
use intern::sym;
use span::Edition;
@ -292,10 +289,6 @@ impl FnTrait {
}
pub fn get_id(self, db: &dyn HirDatabase, krate: Crate) -> Option<TraitId> {
let target = db.lang_item(krate, self.lang_item())?;
match target {
LangItemTarget::Trait(t) => Some(t),
_ => None,
}
self.lang_item().resolve_trait(db, krate)
}
}

View file

@ -36,8 +36,7 @@ use crate::{
pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: Crate) -> impl Iterator<Item = TraitId> + '_ {
[LangItem::Fn, LangItem::FnMut, LangItem::FnOnce]
.into_iter()
.filter_map(move |lang| db.lang_item(krate, lang))
.flat_map(|it| it.as_trait())
.filter_map(move |lang| lang.resolve_trait(db, krate))
}
/// Returns an iterator over the direct super traits (including the trait itself).