1pub mod map;
6pub mod nested_filter;
7pub mod place;
8
9use rustc_data_structures::fingerprint::Fingerprint;
10use rustc_data_structures::sorted_map::SortedMap;
11use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
12use rustc_data_structures::sync::{DynSend, DynSync, try_par_for_each_in};
13use rustc_hir::def::{DefKind, Res};
14use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
15use rustc_hir::lints::DelayedLint;
16use rustc_hir::*;
17use rustc_macros::{Decodable, Encodable, HashStable};
18use rustc_span::{ErrorGuaranteed, ExpnId, Span};
19
20use crate::query::Providers;
21use crate::ty::TyCtxt;
22
23#[derive(Debug, HashStable, Encodable, Decodable)]
26pub struct ModuleItems {
27 add_root: bool,
30 submodules: Box<[OwnerId]>,
31 free_items: Box<[ItemId]>,
32 trait_items: Box<[TraitItemId]>,
33 impl_items: Box<[ImplItemId]>,
34 foreign_items: Box<[ForeignItemId]>,
35 opaques: Box<[LocalDefId]>,
36 body_owners: Box<[LocalDefId]>,
37 nested_bodies: Box<[LocalDefId]>,
38 delayed_lint_items: Box<[OwnerId]>,
40}
41
42impl ModuleItems {
43 pub fn free_items(&self) -> impl Iterator<Item = ItemId> {
50 self.free_items.iter().copied()
51 }
52
53 pub fn trait_items(&self) -> impl Iterator<Item = TraitItemId> {
54 self.trait_items.iter().copied()
55 }
56
57 pub fn delayed_lint_items(&self) -> impl Iterator<Item = OwnerId> {
58 self.delayed_lint_items.iter().copied()
59 }
60
61 pub fn impl_items(&self) -> impl Iterator<Item = ImplItemId> {
64 self.impl_items.iter().copied()
65 }
66
67 pub fn foreign_items(&self) -> impl Iterator<Item = ForeignItemId> {
68 self.foreign_items.iter().copied()
69 }
70
71 pub fn owners(&self) -> impl Iterator<Item = OwnerId> {
72 self.add_root
73 .then_some(CRATE_OWNER_ID)
74 .into_iter()
75 .chain(self.free_items.iter().map(|id| id.owner_id))
76 .chain(self.trait_items.iter().map(|id| id.owner_id))
77 .chain(self.impl_items.iter().map(|id| id.owner_id))
78 .chain(self.foreign_items.iter().map(|id| id.owner_id))
79 }
80
81 pub fn opaques(&self) -> impl Iterator<Item = LocalDefId> {
82 self.opaques.iter().copied()
83 }
84
85 pub fn nested_bodies(&self) -> impl Iterator<Item = LocalDefId> {
87 self.nested_bodies.iter().copied()
88 }
89
90 pub fn definitions(&self) -> impl Iterator<Item = LocalDefId> {
91 self.owners().map(|id| id.def_id)
92 }
93
94 pub fn par_nested_bodies(
96 &self,
97 f: impl Fn(LocalDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
98 ) -> Result<(), ErrorGuaranteed> {
99 try_par_for_each_in(&self.nested_bodies[..], |&&id| f(id))
100 }
101
102 pub fn par_items(
103 &self,
104 f: impl Fn(ItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
105 ) -> Result<(), ErrorGuaranteed> {
106 try_par_for_each_in(&self.free_items[..], |&&id| f(id))
107 }
108
109 pub fn par_trait_items(
110 &self,
111 f: impl Fn(TraitItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
112 ) -> Result<(), ErrorGuaranteed> {
113 try_par_for_each_in(&self.trait_items[..], |&&id| f(id))
114 }
115
116 pub fn par_impl_items(
117 &self,
118 f: impl Fn(ImplItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
119 ) -> Result<(), ErrorGuaranteed> {
120 try_par_for_each_in(&self.impl_items[..], |&&id| f(id))
121 }
122
123 pub fn par_foreign_items(
124 &self,
125 f: impl Fn(ForeignItemId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
126 ) -> Result<(), ErrorGuaranteed> {
127 try_par_for_each_in(&self.foreign_items[..], |&&id| f(id))
128 }
129
130 pub fn par_opaques(
131 &self,
132 f: impl Fn(LocalDefId) -> Result<(), ErrorGuaranteed> + DynSend + DynSync,
133 ) -> Result<(), ErrorGuaranteed> {
134 try_par_for_each_in(&self.opaques[..], |&&id| f(id))
135 }
136}
137
138impl<'tcx> TyCtxt<'tcx> {
139 pub fn parent_module(self, id: HirId) -> LocalModDefId {
140 if !id.is_owner() && self.def_kind(id.owner) == DefKind::Mod {
141 LocalModDefId::new_unchecked(id.owner.def_id)
142 } else {
143 self.parent_module_from_def_id(id.owner.def_id)
144 }
145 }
146
147 pub fn parent_module_from_def_id(self, mut id: LocalDefId) -> LocalModDefId {
148 while let Some(parent) = self.opt_local_parent(id) {
149 id = parent;
150 if self.def_kind(id) == DefKind::Mod {
151 break;
152 }
153 }
154 LocalModDefId::new_unchecked(id)
155 }
156
157 pub fn is_foreign_item(self, def_id: impl Into<DefId>) -> bool {
159 self.opt_parent(def_id.into())
160 .is_some_and(|parent| matches!(self.def_kind(parent), DefKind::ForeignMod))
161 }
162
163 pub fn hash_owner_nodes(
164 self,
165 node: OwnerNode<'_>,
166 bodies: &SortedMap<ItemLocalId, &Body<'_>>,
167 attrs: &SortedMap<ItemLocalId, &[Attribute]>,
168 delayed_lints: &[DelayedLint],
169 define_opaque: Option<&[(Span, LocalDefId)]>,
170 ) -> Hashes {
171 if !self.needs_crate_hash() {
172 return Hashes {
173 opt_hash_including_bodies: None,
174 attrs_hash: None,
175 delayed_lints_hash: None,
176 };
177 }
178
179 self.with_stable_hashing_context(|mut hcx| {
180 let mut stable_hasher = StableHasher::new();
181 node.hash_stable(&mut hcx, &mut stable_hasher);
182 bodies.hash_stable(&mut hcx, &mut stable_hasher);
184 let h1 = stable_hasher.finish();
185
186 let mut stable_hasher = StableHasher::new();
187 attrs.hash_stable(&mut hcx, &mut stable_hasher);
188
189 define_opaque.hash_stable(&mut hcx, &mut stable_hasher);
191
192 let h2 = stable_hasher.finish();
193
194 let mut stable_hasher = StableHasher::new();
196 delayed_lints.hash_stable(&mut hcx, &mut stable_hasher);
197 let h3 = stable_hasher.finish();
198
199 Hashes {
200 opt_hash_including_bodies: Some(h1),
201 attrs_hash: Some(h2),
202 delayed_lints_hash: Some(h3),
203 }
204 })
205 }
206
207 pub fn qpath_is_lang_item(self, qpath: QPath<'_>, lang_item: LangItem) -> bool {
208 self.qpath_lang_item(qpath) == Some(lang_item)
209 }
210
211 pub fn qpath_lang_item(self, qpath: QPath<'_>) -> Option<LangItem> {
213 if let QPath::Resolved(_, path) = qpath
214 && let Res::Def(_, def_id) = path.res
215 {
216 return self.lang_items().from_def_id(def_id);
217 }
218 None
219 }
220
221 pub fn expr_guaranteed_to_constitute_read_for_never(self, expr: &Expr<'_>) -> bool {
233 if !expr.is_syntactic_place_expr() {
239 return true;
240 }
241
242 let parent_node = self.parent_hir_node(expr.hir_id);
243 match parent_node {
244 Node::Expr(parent_expr) => {
245 match parent_expr.kind {
246 ExprKind::AddrOf(..) | ExprKind::Field(..) => false,
250
251 ExprKind::Type(..) | ExprKind::UnsafeBinderCast(..) => {
254 self.expr_guaranteed_to_constitute_read_for_never(parent_expr)
255 }
256
257 ExprKind::Assign(lhs, _, _) => {
258 expr.hir_id != lhs.hir_id
260 }
261
262 ExprKind::Match(scrutinee, arms, _) => {
265 assert_eq!(scrutinee.hir_id, expr.hir_id);
266 arms.iter().all(|arm| arm.pat.is_guaranteed_to_constitute_read_for_never())
267 }
268 ExprKind::Let(LetExpr { init, pat, .. }) => {
269 assert_eq!(init.hir_id, expr.hir_id);
270 pat.is_guaranteed_to_constitute_read_for_never()
271 }
272
273 ExprKind::Array(_)
275 | ExprKind::Call(_, _)
276 | ExprKind::Use(_, _)
277 | ExprKind::MethodCall(_, _, _, _)
278 | ExprKind::Tup(_)
279 | ExprKind::Binary(_, _, _)
280 | ExprKind::Unary(_, _)
281 | ExprKind::Cast(_, _)
282 | ExprKind::DropTemps(_)
283 | ExprKind::If(_, _, _)
284 | ExprKind::Closure(_)
285 | ExprKind::Block(_, _)
286 | ExprKind::AssignOp(_, _, _)
287 | ExprKind::Index(_, _, _)
288 | ExprKind::Break(_, _)
289 | ExprKind::Ret(_)
290 | ExprKind::Become(_)
291 | ExprKind::InlineAsm(_)
292 | ExprKind::Struct(_, _, _)
293 | ExprKind::Repeat(_, _)
294 | ExprKind::Yield(_, _) => true,
295
296 ExprKind::ConstBlock(_)
298 | ExprKind::Loop(_, _, _, _)
299 | ExprKind::Lit(_)
300 | ExprKind::Path(_)
301 | ExprKind::Continue(_)
302 | ExprKind::OffsetOf(_, _)
303 | ExprKind::Err(_) => unreachable!("no sub-expr expected for {:?}", expr.kind),
304 }
305 }
306
307 Node::LetStmt(LetStmt { init: Some(target), pat, .. }) => {
310 assert_eq!(target.hir_id, expr.hir_id);
311 pat.is_guaranteed_to_constitute_read_for_never()
312 }
313
314 Node::Block(_)
316 | Node::Arm(_)
317 | Node::ExprField(_)
318 | Node::AnonConst(_)
319 | Node::ConstBlock(_)
320 | Node::ConstArg(_)
321 | Node::Stmt(_)
322 | Node::Item(Item { kind: ItemKind::Const(..) | ItemKind::Static(..), .. })
323 | Node::TraitItem(TraitItem { kind: TraitItemKind::Const(..), .. })
324 | Node::ImplItem(ImplItem { kind: ImplItemKind::Const(..), .. }) => true,
325
326 Node::TyPat(_) | Node::Pat(_) => {
327 self.dcx().span_delayed_bug(expr.span, "place expr not allowed in pattern");
328 true
329 }
330
331 Node::Param(_)
333 | Node::Item(_)
334 | Node::ForeignItem(_)
335 | Node::TraitItem(_)
336 | Node::ImplItem(_)
337 | Node::Variant(_)
338 | Node::Field(_)
339 | Node::PathSegment(_)
340 | Node::Ty(_)
341 | Node::AssocItemConstraint(_)
342 | Node::TraitRef(_)
343 | Node::PatField(_)
344 | Node::PatExpr(_)
345 | Node::LetStmt(_)
346 | Node::Synthetic
347 | Node::Err(_)
348 | Node::Ctor(_)
349 | Node::Lifetime(_)
350 | Node::GenericParam(_)
351 | Node::Crate(_)
352 | Node::Infer(_)
353 | Node::WherePredicate(_)
354 | Node::PreciseCapturingNonLifetimeArg(_)
355 | Node::OpaqueTy(_) => {
356 unreachable!("no sub-expr expected for {parent_node:?}")
357 }
358 }
359 }
360}
361
362#[derive(Clone, Copy, Debug)]
364pub struct Hashes {
365 pub opt_hash_including_bodies: Option<Fingerprint>,
366 pub attrs_hash: Option<Fingerprint>,
367 pub delayed_lints_hash: Option<Fingerprint>,
368}
369
370pub fn provide(providers: &mut Providers) {
371 providers.hir_crate_items = map::hir_crate_items;
372 providers.crate_hash = map::crate_hash;
373 providers.hir_module_items = map::hir_module_items;
374 providers.local_def_id_to_hir_id = |tcx, def_id| match tcx.hir_crate(()).owners[def_id] {
375 MaybeOwner::Owner(_) => HirId::make_owner(def_id),
376 MaybeOwner::NonOwner(hir_id) => hir_id,
377 MaybeOwner::Phantom => bug!("No HirId for {:?}", def_id),
378 };
379 providers.opt_hir_owner_nodes =
380 |tcx, id| tcx.hir_crate(()).owners.get(id)?.as_owner().map(|i| &i.nodes);
381 providers.hir_owner_parent = |tcx, owner_id| {
382 tcx.opt_local_parent(owner_id.def_id).map_or(CRATE_HIR_ID, |parent_def_id| {
383 let parent_owner_id = tcx.local_def_id_to_hir_id(parent_def_id).owner;
384 HirId {
385 owner: parent_owner_id,
386 local_id: tcx.hir_crate(()).owners[parent_owner_id.def_id]
387 .unwrap()
388 .parenting
389 .get(&owner_id.def_id)
390 .copied()
391 .unwrap_or(ItemLocalId::ZERO),
392 }
393 })
394 };
395 providers.hir_attr_map = |tcx, id| {
396 tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
397 };
398 providers.opt_ast_lowering_delayed_lints =
399 |tcx, id| tcx.hir_crate(()).owners[id.def_id].as_owner().map(|o| &o.delayed_lints);
400 providers.def_span = |tcx, def_id| tcx.hir_span(tcx.local_def_id_to_hir_id(def_id));
401 providers.def_ident_span = |tcx, def_id| {
402 let hir_id = tcx.local_def_id_to_hir_id(def_id);
403 tcx.hir_opt_ident_span(hir_id)
404 };
405 providers.ty_span = |tcx, def_id| {
406 let node = tcx.hir_node_by_def_id(def_id);
407 match node.ty() {
408 Some(ty) => ty.span,
409 None => bug!("{def_id:?} doesn't have a type: {node:#?}"),
410 }
411 };
412 providers.fn_arg_idents = |tcx, def_id| {
413 let node = tcx.hir_node_by_def_id(def_id);
414 if let Some(body_id) = node.body_id() {
415 tcx.arena.alloc_from_iter(tcx.hir_body_param_idents(body_id))
416 } else if let Node::TraitItem(&TraitItem {
417 kind: TraitItemKind::Fn(_, TraitFn::Required(idents)),
418 ..
419 })
420 | Node::ForeignItem(&ForeignItem {
421 kind: ForeignItemKind::Fn(_, idents, _),
422 ..
423 }) = node
424 {
425 idents
426 } else {
427 span_bug!(
428 tcx.hir_span(tcx.local_def_id_to_hir_id(def_id)),
429 "fn_arg_idents: unexpected item {:?}",
430 def_id
431 );
432 }
433 };
434 providers.all_local_trait_impls = |tcx, ()| &tcx.resolutions(()).trait_impls;
435 providers.local_trait_impls =
436 |tcx, trait_id| tcx.resolutions(()).trait_impls.get(&trait_id).map_or(&[], |xs| &xs[..]);
437 providers.expn_that_defined =
438 |tcx, id| tcx.resolutions(()).expn_that_defined.get(&id).copied().unwrap_or(ExpnId::root());
439 providers.in_scope_traits_map = |tcx, id| {
440 tcx.hir_crate(()).owners[id.def_id].as_owner().map(|owner_info| &owner_info.trait_map)
441 };
442}