Skip to content

Commit f6dd41e

Browse files
authored
Merge pull request #19708 from Veykril/push-wrmyowrzkxzz
refactor: De-arc lang item queries
2 parents c505101 + 6355df9 commit f6dd41e

23 files changed

+188
-255
lines changed

crates/hir-def/src/db.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use crate::{
2222
hir::generics::GenericParams,
2323
import_map::ImportMap,
2424
item_tree::{AttrOwner, ItemTree},
25-
lang_item::{self, LangItem, LangItemTarget, LangItems},
25+
lang_item::{self, LangItem},
2626
nameres::{
2727
DefMap, LocalDefMap,
2828
assoc::{ImplItems, TraitItems},
@@ -325,9 +325,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
325325

326326
// endregion:attrs
327327

328-
#[salsa::invoke(LangItems::lang_item_query)]
329-
fn lang_item(&self, start_crate: Crate, item: LangItem) -> Option<LangItemTarget>;
330-
331328
#[salsa::invoke(ImportMap::import_map_query)]
332329
fn import_map(&self, krate: Crate) -> Arc<ImportMap>;
333330

@@ -349,9 +346,6 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + SourceDatabase {
349346

350347
// endregion:visibilities
351348

352-
#[salsa::invoke(LangItems::crate_lang_items_query)]
353-
fn crate_lang_items(&self, krate: Crate) -> Option<Arc<LangItems>>;
354-
355349
#[salsa::invoke(crate::lang_item::notable_traits_in_deps)]
356350
fn notable_traits_in_deps(&self, krate: Crate) -> Arc<[Arc<[TraitId]>]>;
357351
#[salsa::invoke(crate::lang_item::crate_notable_traits)]

crates/hir-def/src/lang_item.rs

+101-86
Original file line numberDiff line numberDiff line change
@@ -83,104 +83,99 @@ impl LangItemTarget {
8383
}
8484
}
8585

86-
#[derive(Default, Debug, Clone, PartialEq, Eq)]
87-
pub struct LangItems {
88-
items: FxHashMap<LangItem, LangItemTarget>,
89-
}
86+
/// Salsa query. This will look for lang items in a specific crate.
87+
#[salsa::tracked(return_ref)]
88+
pub fn crate_lang_items(db: &dyn DefDatabase, krate: Crate) -> Option<Box<LangItems>> {
89+
let _p = tracing::info_span!("crate_lang_items_query").entered();
9090

91-
impl LangItems {
92-
pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
93-
self.items.get(&item).copied()
94-
}
91+
let mut lang_items = LangItems::default();
9592

96-
/// Salsa query. This will look for lang items in a specific crate.
97-
pub(crate) fn crate_lang_items_query(
98-
db: &dyn DefDatabase,
99-
krate: Crate,
100-
) -> Option<Arc<LangItems>> {
101-
let _p = tracing::info_span!("crate_lang_items_query").entered();
102-
103-
let mut lang_items = LangItems::default();
93+
let crate_def_map = db.crate_def_map(krate);
10494

105-
let crate_def_map = db.crate_def_map(krate);
95+
for (_, module_data) in crate_def_map.modules() {
96+
for impl_def in module_data.scope.impls() {
97+
lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
98+
for &(_, assoc) in db.impl_items(impl_def).items.iter() {
99+
match assoc {
100+
AssocItemId::FunctionId(f) => {
101+
lang_items.collect_lang_item(db, f, LangItemTarget::Function)
102+
}
103+
AssocItemId::TypeAliasId(t) => {
104+
lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
105+
}
106+
AssocItemId::ConstId(_) => (),
107+
}
108+
}
109+
}
106110

107-
for (_, module_data) in crate_def_map.modules() {
108-
for impl_def in module_data.scope.impls() {
109-
lang_items.collect_lang_item(db, impl_def, LangItemTarget::ImplDef);
110-
for &(_, assoc) in db.impl_items(impl_def).items.iter() {
111-
match assoc {
111+
for def in module_data.scope.declarations() {
112+
match def {
113+
ModuleDefId::TraitId(trait_) => {
114+
lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
115+
db.trait_items(trait_).items.iter().for_each(|&(_, assoc_id)| match assoc_id {
112116
AssocItemId::FunctionId(f) => {
113-
lang_items.collect_lang_item(db, f, LangItemTarget::Function)
117+
lang_items.collect_lang_item(db, f, LangItemTarget::Function);
114118
}
115-
AssocItemId::TypeAliasId(t) => {
116-
lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias)
119+
AssocItemId::TypeAliasId(alias) => {
120+
lang_items.collect_lang_item(db, alias, LangItemTarget::TypeAlias)
117121
}
118-
AssocItemId::ConstId(_) => (),
119-
}
122+
AssocItemId::ConstId(_) => {}
123+
});
120124
}
121-
}
122-
123-
for def in module_data.scope.declarations() {
124-
match def {
125-
ModuleDefId::TraitId(trait_) => {
126-
lang_items.collect_lang_item(db, trait_, LangItemTarget::Trait);
127-
db.trait_items(trait_).items.iter().for_each(
128-
|&(_, assoc_id)| match assoc_id {
129-
AssocItemId::FunctionId(f) => {
130-
lang_items.collect_lang_item(db, f, LangItemTarget::Function);
131-
}
132-
AssocItemId::TypeAliasId(alias) => lang_items.collect_lang_item(
133-
db,
134-
alias,
135-
LangItemTarget::TypeAlias,
136-
),
137-
AssocItemId::ConstId(_) => {}
138-
},
139-
);
140-
}
141-
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
142-
lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
143-
db.enum_variants(e).variants.iter().for_each(|&(id, _)| {
144-
lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
145-
});
146-
}
147-
ModuleDefId::AdtId(AdtId::StructId(s)) => {
148-
lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
149-
}
150-
ModuleDefId::AdtId(AdtId::UnionId(u)) => {
151-
lang_items.collect_lang_item(db, u, LangItemTarget::Union);
152-
}
153-
ModuleDefId::FunctionId(f) => {
154-
lang_items.collect_lang_item(db, f, LangItemTarget::Function);
155-
}
156-
ModuleDefId::StaticId(s) => {
157-
lang_items.collect_lang_item(db, s, LangItemTarget::Static);
158-
}
159-
ModuleDefId::TypeAliasId(t) => {
160-
lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
161-
}
162-
_ => {}
125+
ModuleDefId::AdtId(AdtId::EnumId(e)) => {
126+
lang_items.collect_lang_item(db, e, LangItemTarget::EnumId);
127+
db.enum_variants(e).variants.iter().for_each(|&(id, _)| {
128+
lang_items.collect_lang_item(db, id, LangItemTarget::EnumVariant);
129+
});
130+
}
131+
ModuleDefId::AdtId(AdtId::StructId(s)) => {
132+
lang_items.collect_lang_item(db, s, LangItemTarget::Struct);
133+
}
134+
ModuleDefId::AdtId(AdtId::UnionId(u)) => {
135+
lang_items.collect_lang_item(db, u, LangItemTarget::Union);
163136
}
137+
ModuleDefId::FunctionId(f) => {
138+
lang_items.collect_lang_item(db, f, LangItemTarget::Function);
139+
}
140+
ModuleDefId::StaticId(s) => {
141+
lang_items.collect_lang_item(db, s, LangItemTarget::Static);
142+
}
143+
ModuleDefId::TypeAliasId(t) => {
144+
lang_items.collect_lang_item(db, t, LangItemTarget::TypeAlias);
145+
}
146+
_ => {}
164147
}
165148
}
149+
}
166150

167-
if lang_items.items.is_empty() { None } else { Some(Arc::new(lang_items)) }
151+
if lang_items.items.is_empty() { None } else { Some(Box::new(lang_items)) }
152+
}
153+
154+
/// Salsa query. Look for a lang item, starting from the specified crate and recursively
155+
/// traversing its dependencies.
156+
#[salsa::tracked]
157+
pub fn lang_item(
158+
db: &dyn DefDatabase,
159+
start_crate: Crate,
160+
item: LangItem,
161+
) -> Option<LangItemTarget> {
162+
let _p = tracing::info_span!("lang_item_query").entered();
163+
if let Some(target) =
164+
crate_lang_items(db, start_crate).as_ref().and_then(|it| it.items.get(&item).copied())
165+
{
166+
return Some(target);
168167
}
168+
start_crate.data(db).dependencies.iter().find_map(|dep| lang_item(db, dep.crate_id, item))
169+
}
169170

170-
/// Salsa query. Look for a lang item, starting from the specified crate and recursively
171-
/// traversing its dependencies.
172-
pub(crate) fn lang_item_query(
173-
db: &dyn DefDatabase,
174-
start_crate: Crate,
175-
item: LangItem,
176-
) -> Option<LangItemTarget> {
177-
let _p = tracing::info_span!("lang_item_query").entered();
178-
if let Some(target) =
179-
db.crate_lang_items(start_crate).and_then(|it| it.items.get(&item).copied())
180-
{
181-
return Some(target);
182-
}
183-
start_crate.data(db).dependencies.iter().find_map(|dep| db.lang_item(dep.crate_id, item))
171+
#[derive(Default, Debug, Clone, PartialEq, Eq)]
172+
pub struct LangItems {
173+
items: FxHashMap<LangItem, LangItemTarget>,
174+
}
175+
176+
impl LangItems {
177+
pub fn target(&self, item: LangItem) -> Option<LangItemTarget> {
178+
self.items.get(&item).copied()
184179
}
185180

186181
fn collect_lang_item<T>(
@@ -269,18 +264,38 @@ macro_rules! language_item_table {
269264
}
270265

271266
impl LangItem {
267+
pub fn resolve_function(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<FunctionId> {
268+
lang_item(db, start_crate, self).and_then(|t| t.as_function())
269+
}
270+
271+
pub fn resolve_trait(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<TraitId> {
272+
lang_item(db, start_crate, self).and_then(|t| t.as_trait())
273+
}
274+
275+
pub fn resolve_enum(self, db: &dyn DefDatabase, start_crate: Crate) -> Option<EnumId> {
276+
lang_item(db, start_crate, self).and_then(|t| t.as_enum())
277+
}
278+
279+
pub fn resolve_type_alias(
280+
self,
281+
db: &dyn DefDatabase,
282+
start_crate: Crate,
283+
) -> Option<TypeAliasId> {
284+
lang_item(db, start_crate, self).and_then(|t| t.as_type_alias())
285+
}
286+
272287
/// Opposite of [`LangItem::name`]
273288
pub fn from_name(name: &hir_expand::name::Name) -> Option<Self> {
274289
Self::from_symbol(name.symbol())
275290
}
276291

277292
pub fn path(&self, db: &dyn DefDatabase, start_crate: Crate) -> Option<Path> {
278-
let t = db.lang_item(start_crate, *self)?;
293+
let t = lang_item(db, start_crate, *self)?;
279294
Some(Path::LangItem(t, None))
280295
}
281296

282297
pub fn ty_rel_path(&self, db: &dyn DefDatabase, start_crate: Crate, seg: Name) -> Option<Path> {
283-
let t = db.lang_item(start_crate, *self)?;
298+
let t = lang_item(db, start_crate, *self)?;
284299
Some(Path::LangItem(t, Some(seg)))
285300
}
286301
}

crates/hir-ty/src/autoderef.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,13 @@ pub(crate) fn deref_by_trait(
198198
// blanked impl on `Deref`.
199199
#[expect(clippy::overly_complex_bool_expr)]
200200
if use_receiver_trait && false {
201-
if let Some(receiver) =
202-
db.lang_item(table.trait_env.krate, LangItem::Receiver).and_then(|l| l.as_trait())
203-
{
201+
if let Some(receiver) = LangItem::Receiver.resolve_trait(db, table.trait_env.krate) {
204202
return Some(receiver);
205203
}
206204
}
207205
// Old rustc versions might not have `Receiver` trait.
208206
// Fallback to `Deref` if they don't
209-
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())
207+
LangItem::Deref.resolve_trait(db, table.trait_env.krate)
210208
};
211209
let trait_id = trait_id()?;
212210
let target =

crates/hir-ty/src/chalk_db.rs

+7-17
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use hir_def::{
1616
AssocItemId, BlockId, CallableDefId, GenericDefId, HasModule, ItemContainerId, Lookup,
1717
TypeAliasId, VariantId,
1818
hir::Movability,
19-
lang_item::{LangItem, LangItemTarget},
19+
lang_item::LangItem,
2020
signatures::{ImplFlags, StructFlags, TraitFlags},
2121
};
2222

@@ -262,10 +262,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
262262
well_known_trait: rust_ir::WellKnownTrait,
263263
) -> Option<chalk_ir::TraitId<Interner>> {
264264
let lang_attr = lang_item_from_well_known_trait(well_known_trait);
265-
let trait_ = match self.db.lang_item(self.krate, lang_attr) {
266-
Some(LangItemTarget::Trait(trait_)) => trait_,
267-
_ => return None,
268-
};
265+
let trait_ = lang_attr.resolve_trait(self.db, self.krate)?;
269266
Some(to_chalk_trait_id(trait_))
270267
}
271268

@@ -306,11 +303,8 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
306303
chalk_ir::Binders::new(binders, bound)
307304
}
308305
crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
309-
if let Some((future_trait, future_output)) = self
310-
.db
311-
.lang_item(self.krate, LangItem::Future)
312-
.and_then(|item| item.as_trait())
313-
.and_then(|trait_| {
306+
if let Some((future_trait, future_output)) =
307+
LangItem::Future.resolve_trait(self.db, self.krate).and_then(|trait_| {
314308
let alias = self
315309
.db
316310
.trait_items(trait_)
@@ -338,10 +332,7 @@ impl chalk_solve::RustIrDatabase<Interner> for ChalkContext<'_> {
338332
});
339333
let mut binder = vec![];
340334
binder.push(crate::wrap_empty_binders(impl_bound));
341-
let sized_trait = self
342-
.db
343-
.lang_item(self.krate, LangItem::Sized)
344-
.and_then(|item| item.as_trait());
335+
let sized_trait = LangItem::Sized.resolve_trait(self.db, self.krate);
345336
if let Some(sized_trait_) = sized_trait {
346337
let sized_bound = WhereClause::Implemented(TraitRef {
347338
trait_id: to_chalk_trait_id(sized_trait_),
@@ -660,9 +651,8 @@ pub(crate) fn associated_ty_data_query(
660651
}
661652

662653
if !ctx.unsized_types.contains(&self_ty) {
663-
let sized_trait = db
664-
.lang_item(resolver.krate(), LangItem::Sized)
665-
.and_then(|lang_item| lang_item.as_trait().map(to_chalk_trait_id));
654+
let sized_trait =
655+
LangItem::Sized.resolve_trait(db, resolver.krate()).map(to_chalk_trait_id);
666656
let sized_bound = sized_trait.into_iter().map(|sized_trait| {
667657
let trait_bound =
668658
rust_ir::TraitBound { trait_id: sized_trait, args_no_self: Default::default() };

crates/hir-ty/src/chalk_ext.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,7 @@ impl TyExt for Ty {
251251
match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
252252
ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
253253
let krate = def.module(db).krate();
254-
if let Some(future_trait) =
255-
db.lang_item(krate, LangItem::Future).and_then(|item| item.as_trait())
256-
{
254+
if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
257255
// This is only used by type walking.
258256
// Parameters will be walked outside, and projection predicate is not used.
259257
// So just provide the Future trait.
@@ -364,8 +362,7 @@ impl TyExt for Ty {
364362

365363
fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool {
366364
let crate_id = owner.module(db).krate();
367-
let Some(copy_trait) = db.lang_item(crate_id, LangItem::Copy).and_then(|it| it.as_trait())
368-
else {
365+
let Some(copy_trait) = LangItem::Copy.resolve_trait(db, crate_id) else {
369366
return false;
370367
};
371368
let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(self).build();

crates/hir-ty/src/diagnostics/expr.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -482,9 +482,8 @@ struct FilterMapNextChecker {
482482
impl FilterMapNextChecker {
483483
fn new(resolver: &hir_def::resolver::Resolver, db: &dyn HirDatabase) -> Self {
484484
// Find and store the FunctionIds for Iterator::filter_map and Iterator::next
485-
let (next_function_id, filter_map_function_id) = match db
486-
.lang_item(resolver.krate(), LangItem::IteratorNext)
487-
.and_then(|it| it.as_function())
485+
let (next_function_id, filter_map_function_id) = match LangItem::IteratorNext
486+
.resolve_function(db, resolver.krate())
488487
{
489488
Some(next_function_id) => (
490489
Some(next_function_id),

0 commit comments

Comments
 (0)