1#![feature(associated_type_defaults)]
3#![feature(default_field_values)]
4#![feature(try_blocks)]
5mod diagnostics;
8
9use std::marker::PhantomData;
10use std::ops::ControlFlow;
11use std::{debug_assert_matches, fmt};
12
13use diagnostics::{
14 FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
15 ItemIsPrivate, PrivateInterfacesOrBoundsLint, ReportEffectiveVisibility, UnnameableTypesLint,
16 UnnamedItemIsPrivate,
17};
18use rustc_ast::visit::{VisitorResult, try_visit};
19use rustc_data_structures::fx::{FxHashMap, FxHashSet};
20use rustc_data_structures::indexmap::IndexSet;
21use rustc_data_structures::intern::Interned;
22use rustc_errors::{MultiSpan, listify};
23use rustc_hir::def::{CtorOf, DefKind, Res};
24use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
25use rustc_hir::intravisit::{self, InferKind, Visitor};
26use rustc_hir::{self as hir, AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind, find_attr};
27use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
28use rustc_middle::query::Providers;
29use rustc_middle::ty::print::PrintTraitRefExt as _;
30use rustc_middle::ty::{
31 self, AssocContainer, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
32 TypeVisitable, TypeVisitor,
33};
34use rustc_middle::{bug, span_bug};
35use rustc_session::lint;
36use rustc_span::{Ident, Span, Symbol, sym};
37use tracing::debug;
38
39struct LazyDefPathStr<'tcx> {
44 def_id: DefId,
45 tcx: TyCtxt<'tcx>,
46}
47
48impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 f.write_fmt(format_args!("{0}", self.tcx.def_path_str(self.def_id)))write!(f, "{}", self.tcx.def_path_str(self.def_id))
51 }
52}
53
54pub trait DefIdVisitor<'tcx> {
63 type Result: VisitorResult = ();
64 const SHALLOW: bool = false;
65 fn skip_assoc_tys(&self) -> bool {
66 false
67 }
68
69 fn tcx(&self) -> TyCtxt<'tcx>;
70 fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
74 -> Self::Result;
75
76 fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
78 DefIdVisitorSkeleton {
79 def_id_visitor: self,
80 visited_tys: Default::default(),
81 dummy: Default::default(),
82 }
83 }
84 fn visit(&mut self, ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
85 ty_fragment.visit_with(&mut self.skeleton())
86 }
87 fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> Self::Result {
88 self.skeleton().visit_trait(trait_ref)
89 }
90 fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> Self::Result {
91 self.skeleton().visit_clauses(predicates.predicates)
92 }
93 fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result {
94 self.skeleton().visit_clauses(clauses)
95 }
96}
97
98pub struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
99 def_id_visitor: &'v mut V,
100 visited_tys: FxHashSet<Ty<'tcx>>,
101 dummy: PhantomData<TyCtxt<'tcx>>,
102}
103
104impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
105where
106 V: DefIdVisitor<'tcx> + ?Sized,
107{
108 fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result {
109 let TraitRef { def_id, args, .. } = trait_ref;
110 match ::rustc_ast_ir::visit::VisitorResult::branch(self.def_id_visitor.visit_def_id(def_id,
"trait", &trait_ref.print_only_trait_path())) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.def_id_visitor.visit_def_id(
111 def_id,
112 "trait",
113 &trait_ref.print_only_trait_path()
114 ));
115 if V::SHALLOW { V::Result::output() } else { args.visit_with(self) }
116 }
117
118 fn visit_projection_term(&mut self, projection: ty::AliasTerm<'tcx>) -> V::Result {
119 let tcx = self.def_id_visitor.tcx();
120 let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx);
121 match ::rustc_ast_ir::visit::VisitorResult::branch(self.visit_trait(trait_ref))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.visit_trait(trait_ref));
122 if V::SHALLOW {
123 V::Result::output()
124 } else {
125 V::Result::from_branch(
126 assoc_args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
127 )
128 }
129 }
130
131 fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result {
132 match clause.kind().skip_binder() {
133 ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
134 self.visit_trait(trait_ref)
135 }
136 ty::ClauseKind::HostEffect(pred) => {
137 match ::rustc_ast_ir::visit::VisitorResult::branch(self.visit_trait(pred.trait_ref))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.visit_trait(pred.trait_ref));
138 pred.constness.visit_with(self)
139 }
140 ty::ClauseKind::Projection(ty::ProjectionPredicate {
141 projection_term: projection_ty,
142 term,
143 }) => {
144 match ::rustc_ast_ir::visit::VisitorResult::branch(term.visit_with(self)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(term.visit_with(self));
145 self.visit_projection_term(projection_ty)
146 }
147 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
148 ty::ClauseKind::RegionOutlives(..) => V::Result::output(),
149 ty::ClauseKind::ConstArgHasType(ct, ty) => {
150 match ::rustc_ast_ir::visit::VisitorResult::branch(ct.visit_with(self)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(ct.visit_with(self));
151 ty.visit_with(self)
152 }
153 ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
154 ty::ClauseKind::WellFormed(term) => term.visit_with(self),
155 ty::ClauseKind::UnstableFeature(_) => V::Result::output(),
156 }
157 }
158
159 fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result {
160 for &(clause, _) in clauses {
161 match ::rustc_ast_ir::visit::VisitorResult::branch(self.visit_clause(clause))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.visit_clause(clause));
162 }
163 V::Result::output()
164 }
165}
166
167impl<'tcx, V> TypeVisitor<TyCtxt<'tcx>> for DefIdVisitorSkeleton<'_, 'tcx, V>
168where
169 V: DefIdVisitor<'tcx> + ?Sized,
170{
171 type Result = V::Result;
172
173 fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result {
174 self.visit_clause(p.as_clause().unwrap())
175 }
176
177 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
178 let tcx = self.def_id_visitor.tcx();
179 let ty_kind = *ty.kind();
182 match ty_kind {
183 ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), ..)
184 | ty::Foreign(def_id)
185 | ty::FnDef(def_id, ..)
186 | ty::Closure(def_id, ..)
187 | ty::CoroutineClosure(def_id, ..)
188 | ty::Coroutine(def_id, ..) => {
189 match ::rustc_ast_ir::visit::VisitorResult::branch(self.def_id_visitor.visit_def_id(def_id,
"type", &ty)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.def_id_visitor.visit_def_id(def_id, "type", &ty));
190 if V::SHALLOW {
191 return V::Result::output();
192 }
193 if let ty::FnDef(..) = ty_kind {
197 match ::rustc_ast_ir::visit::VisitorResult::branch(tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip().visit_with(self))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(
199 tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip().visit_with(self)
200 );
201 }
202 if let Some(assoc_item) = tcx.opt_associated_item(def_id)
207 && let Some(impl_def_id) = assoc_item.impl_container(tcx)
208 {
209 match ::rustc_ast_ir::visit::VisitorResult::branch(tcx.type_of(impl_def_id).instantiate_identity().skip_norm_wip().visit_with(self))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(
210 tcx.type_of(impl_def_id)
211 .instantiate_identity()
212 .skip_norm_wip()
213 .visit_with(self)
214 );
215 }
216 }
217 ty::Alias(
218 _,
219 data @ ty::AliasTy {
220 kind:
221 kind @ (ty::Inherent { def_id }
222 | ty::Free { def_id }
223 | ty::Projection { def_id }),
224 ..
225 },
226 ) => {
227 if self.def_id_visitor.skip_assoc_tys() {
228 return V::Result::output();
234 }
235 if !self.visited_tys.insert(ty) {
236 return V::Result::output();
240 }
241
242 match ::rustc_ast_ir::visit::VisitorResult::branch(self.def_id_visitor.visit_def_id(def_id,
match kind {
ty::Inherent { .. } | ty::Projection { .. } =>
"associated type",
ty::Free { .. } => "type alias",
ty::Opaque { .. } =>
::core::panicking::panic("internal error: entered unreachable code"),
}, &LazyDefPathStr { def_id, tcx })) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.def_id_visitor.visit_def_id(
243 def_id,
244 match kind {
245 ty::Inherent { .. } | ty::Projection { .. } => "associated type",
246 ty::Free { .. } => "type alias",
247 ty::Opaque { .. } => unreachable!(),
248 },
249 &LazyDefPathStr { def_id, tcx },
250 ));
251
252 return if V::SHALLOW {
254 V::Result::output()
255 } else if #[allow(non_exhaustive_omitted_patterns)] match kind {
ty::Projection { .. } => true,
_ => false,
}matches!(kind, ty::Projection { .. }) {
256 self.visit_projection_term(data.into())
257 } else {
258 V::Result::from_branch(
259 data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
260 )
261 };
262 }
263 ty::Dynamic(predicates, ..) => {
264 for predicate in predicates {
267 let trait_ref = match predicate.skip_binder() {
268 ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
269 ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
270 ty::ExistentialPredicate::AutoTrait(def_id) => {
271 ty::ExistentialTraitRef::new(tcx, def_id, ty::GenericArgs::empty())
272 }
273 };
274 let ty::ExistentialTraitRef { def_id, .. } = trait_ref;
275 match ::rustc_ast_ir::visit::VisitorResult::branch(self.def_id_visitor.visit_def_id(def_id,
"trait", &trait_ref)) {
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref));
276 }
277 }
278 ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => {
279 if self.visited_tys.insert(ty) {
281 match ::rustc_ast_ir::visit::VisitorResult::branch(self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder()))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder()));
289 }
290 }
291 ty::Bool
294 | ty::Char
295 | ty::Int(..)
296 | ty::Uint(..)
297 | ty::Float(..)
298 | ty::Str
299 | ty::Never
300 | ty::Array(..)
301 | ty::Slice(..)
302 | ty::Tuple(..)
303 | ty::RawPtr(..)
304 | ty::Ref(..)
305 | ty::Pat(..)
306 | ty::FnPtr(..)
307 | ty::UnsafeBinder(_)
308 | ty::Param(..)
309 | ty::Bound(..)
310 | ty::Error(_)
311 | ty::CoroutineWitness(..) => {}
312 ty::Placeholder(..) | ty::Infer(..) => {
313 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type: {0:?}", ty))bug!("unexpected type: {:?}", ty)
314 }
315 }
316
317 if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) }
318 }
319
320 fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
321 let tcx = self.def_id_visitor.tcx();
322 tcx.expand_abstract_consts(c).super_visit_with(self)
323 }
324}
325
326fn assoc_has_type_of(tcx: TyCtxt<'_>, item: &ty::AssocItem) -> bool {
327 if let ty::AssocKind::Type { data: ty::AssocTypeData::Normal(..) } = item.kind
328 && let hir::Node::TraitItem(item) =
329 tcx.hir_node(tcx.local_def_id_to_hir_id(item.def_id.expect_local()))
330 && let hir::TraitItemKind::Type(_, None) = item.kind
331 {
332 false
333 } else {
334 true
335 }
336}
337
338fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
339 if vis1.greater_than(vis2, tcx) { vis2 } else { vis1 }
340}
341
342struct FindMin<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> {
344 tcx: TyCtxt<'tcx>,
345 effective_visibilities: &'a EffectiveVisibilities,
346 min: VL,
347}
348
349impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
350 for FindMin<'a, 'tcx, VL, SHALLOW>
351{
352 const SHALLOW: bool = SHALLOW;
353 fn skip_assoc_tys(&self) -> bool {
354 true
355 }
356 fn tcx(&self) -> TyCtxt<'tcx> {
357 self.tcx
358 }
359 fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
360 if let Some(def_id) = def_id.as_local() {
361 self.min = VL::new_min(self, def_id);
362 }
363 }
364}
365
366trait VisibilityLike: Sized {
367 const MAX: Self;
368 fn new_min<const SHALLOW: bool>(
369 find: &FindMin<'_, '_, Self, SHALLOW>,
370 def_id: LocalDefId,
371 ) -> Self;
372
373 fn of_impl<const SHALLOW: bool>(
376 def_id: LocalDefId,
377 of_trait: bool,
378 tcx: TyCtxt<'_>,
379 effective_visibilities: &EffectiveVisibilities,
380 ) -> Self {
381 let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
382 find.visit(tcx.type_of(def_id).instantiate_identity().skip_norm_wip());
383 if of_trait {
384 find.visit_trait(tcx.impl_trait_ref(def_id).instantiate_identity().skip_norm_wip());
385 }
386 find.min
387 }
388}
389
390impl VisibilityLike for ty::Visibility {
391 const MAX: Self = ty::Visibility::Public;
392 fn new_min<const SHALLOW: bool>(
393 find: &FindMin<'_, '_, Self, SHALLOW>,
394 def_id: LocalDefId,
395 ) -> Self {
396 min(find.tcx.local_visibility(def_id), find.min, find.tcx)
397 }
398}
399
400impl VisibilityLike for EffectiveVisibility {
401 const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public);
402 fn new_min<const SHALLOW: bool>(
403 find: &FindMin<'_, '_, Self, SHALLOW>,
404 def_id: LocalDefId,
405 ) -> Self {
406 let effective_vis =
407 find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| {
408 let private_vis = ty::Visibility::Restricted(
409 find.tcx.parent_module_from_def_id(def_id).to_local_def_id(),
410 );
411 EffectiveVisibility::from_vis(private_vis)
412 });
413
414 effective_vis.min(find.min, find.tcx)
415 }
416}
417
418type DefIdsToImpls = FxHashMap<LocalDefId, FxHashSet<LocalDefId>>;
419
420struct DefIdsToImplsCollector<'tcx, 'a> {
423 tcx: TyCtxt<'tcx>,
424 def_ids_to_impls: &'a mut DefIdsToImpls,
425 impl_def_id: LocalDefId,
426}
427
428impl<'tcx, 'a> DefIdsToImplsCollector<'tcx, 'a> {
429 fn collect(tcx: TyCtxt<'tcx>) -> DefIdsToImpls {
430 let mut def_ids_to_impls = Default::default();
431 for item in tcx.hir_free_items() {
432 let impl_def_id = item.owner_id.def_id;
433 let DefKind::Impl { of_trait } = tcx.def_kind(impl_def_id) else {
434 continue;
435 };
436
437 let mut visitor = DefIdsToImplsCollector {
439 tcx,
440 impl_def_id,
441 def_ids_to_impls: &mut def_ids_to_impls,
442 };
443
444 visitor.visit(tcx.type_of(impl_def_id).instantiate_identity().skip_norm_wip());
445 if of_trait {
446 visitor.visit_trait(
447 tcx.impl_trait_ref(impl_def_id).instantiate_identity().skip_norm_wip(),
448 );
449 }
450 }
451
452 def_ids_to_impls
453 }
454}
455
456impl<'tcx, 'a> DefIdVisitor<'tcx> for DefIdsToImplsCollector<'tcx, 'a> {
457 const SHALLOW: bool = true;
458 fn skip_assoc_tys(&self) -> bool {
459 true
460 }
461 fn tcx(&self) -> TyCtxt<'tcx> {
462 self.tcx
463 }
464 fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
465 if let Some(def_id) = def_id.as_local() {
466 if true {
{
match self.tcx.def_kind(def_id) {
DefKind::Enum | DefKind::Union | DefKind::Struct |
DefKind::ForeignTy | DefKind::Trait => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"DefKind::Enum | DefKind::Union | DefKind::Struct | DefKind::ForeignTy |\nDefKind::Trait",
::core::option::Option::None);
}
}
};
};debug_assert_matches!(
467 self.tcx.def_kind(def_id),
468 DefKind::Enum
469 | DefKind::Union
470 | DefKind::Struct
471 | DefKind::ForeignTy
472 | DefKind::Trait
473 );
474 self.def_ids_to_impls.entry(def_id).or_default().insert(self.impl_def_id);
475 }
476 }
477}
478
479struct EmbargoVisitor<'tcx> {
481 tcx: TyCtxt<'tcx>,
482 effective_visibilities: EffectiveVisibilities,
484 queue: IndexSet<LocalDefId>,
486 def_ids_to_impls: DefIdsToImpls,
488}
489
490struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
491 effective_vis: EffectiveVisibility,
492 item_def_id: LocalDefId,
493 ev: &'a mut EmbargoVisitor<'tcx>,
494 level: Level,
495}
496
497impl<'tcx> EmbargoVisitor<'tcx> {
498 fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
499 self.effective_visibilities.effective_vis(def_id).copied()
500 }
501
502 fn update(
504 &mut self,
505 def_id: LocalDefId,
506 inherited_effective_vis: EffectiveVisibility,
507 level: Level,
508 ) {
509 let nominal_vis = self.tcx.local_visibility(def_id);
510 self.update_eff_vis(def_id, inherited_effective_vis, Some(nominal_vis), level);
511 }
512
513 fn update_eff_vis(
514 &mut self,
515 def_id: LocalDefId,
516 inherited_effective_vis: EffectiveVisibility,
517 max_vis: Option<ty::Visibility>,
518 level: Level,
519 ) -> bool {
520 let private_vis =
522 ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id).into());
523 if max_vis != Some(private_vis) {
524 return self.effective_visibilities.update(
525 def_id,
526 max_vis,
527 private_vis,
528 inherited_effective_vis,
529 level,
530 self.tcx,
531 );
532 }
533 false
534 }
535
536 fn reach(
537 &mut self,
538 def_id: LocalDefId,
539 effective_vis: EffectiveVisibility,
540 ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
541 ReachEverythingInTheInterfaceVisitor {
542 effective_vis,
543 item_def_id: def_id,
544 ev: self,
545 level: Level::Reachable,
546 }
547 }
548
549 fn reach_through_impl_trait(
550 &mut self,
551 def_id: LocalDefId,
552 effective_vis: EffectiveVisibility,
553 ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
554 ReachEverythingInTheInterfaceVisitor {
555 effective_vis,
556 item_def_id: def_id,
557 ev: self,
558 level: Level::ReachableThroughImplTrait,
559 }
560 }
561}
562
563impl<'tcx> EmbargoVisitor<'tcx> {
564 fn check_assoc_item(&mut self, item: &ty::AssocItem, item_ev: EffectiveVisibility) {
565 let def_id = item.def_id.expect_local();
566 let tcx = self.tcx;
567 let mut reach = self.reach(def_id, item_ev);
568 reach.generics().predicates();
569 if assoc_has_type_of(tcx, item) {
570 reach.ty();
571 }
572 if item.is_type() && item.container == AssocContainer::Trait {
573 reach.bounds();
574 }
575 }
576
577 fn check_def_id(&mut self, def_id: LocalDefId) {
578 let item_ev = self.get(def_id);
581 let def_kind = self.tcx.def_kind(def_id);
582 match def_kind {
583 DefKind::Use | DefKind::ExternCrate | DefKind::GlobalAsm => {}
585 DefKind::Mod => {}
587 DefKind::Macro { .. } => {}
589 DefKind::ForeignTy
590 | DefKind::Const { .. }
591 | DefKind::Static { .. }
592 | DefKind::Fn
593 | DefKind::TyAlias => {
594 if let Some(item_ev) = item_ev {
595 self.reach(def_id, item_ev).generics().predicates().ty();
596 }
597 }
598 DefKind::Trait => {
599 if let Some(item_ev) = item_ev {
600 self.reach(def_id, item_ev).generics().predicates();
601
602 for assoc_item in self.tcx.associated_items(def_id).in_definition_order() {
603 let def_id = assoc_item.def_id.expect_local();
604 self.update(def_id, item_ev, Level::Reachable);
605
606 self.check_assoc_item(assoc_item, item_ev);
607 }
608 }
609 }
610 DefKind::TraitAlias => {
611 if let Some(item_ev) = item_ev {
612 self.reach(def_id, item_ev).generics().predicates();
613 }
614 }
615 DefKind::Impl { of_trait } => {
616 let item_ev = EffectiveVisibility::of_impl::<true>(
627 def_id,
628 of_trait,
629 self.tcx,
630 &self.effective_visibilities,
631 );
632
633 self.update_eff_vis(def_id, item_ev, None, Level::Direct);
634
635 {
636 let mut reach = self.reach(def_id, item_ev);
637 reach.generics().predicates().ty();
638 if of_trait {
639 reach.trait_ref();
640 }
641 }
642
643 for assoc_item in self.tcx.associated_items(def_id).in_definition_order() {
644 let def_id = assoc_item.def_id.expect_local();
645 let max_vis =
646 if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) };
647 self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);
648
649 if let Some(impl_item_ev) = self.get(def_id) {
650 self.check_assoc_item(assoc_item, impl_item_ev);
651 }
652 }
653 }
654 DefKind::Enum => {
655 if let Some(item_ev) = item_ev {
656 self.reach(def_id, item_ev).generics().predicates();
657 }
658 let def = self.tcx.adt_def(def_id);
659 for variant in def.variants() {
660 if let Some(item_ev) = item_ev {
661 self.update(variant.def_id.expect_local(), item_ev, Level::Reachable);
662 }
663
664 if let Some(variant_ev) = self.get(variant.def_id.expect_local()) {
665 if let Some(ctor_def_id) = variant.ctor_def_id() {
666 self.update(ctor_def_id.expect_local(), variant_ev, Level::Reachable);
667 }
668
669 for field in &variant.fields {
670 let field = field.did.expect_local();
671 self.update(field, variant_ev, Level::Reachable);
672 self.reach(field, variant_ev).ty();
673 }
674 self.reach(def_id, variant_ev).ty();
677 }
678 if let Some(ctor_def_id) = variant.ctor_def_id() {
679 if let Some(ctor_ev) = self.get(ctor_def_id.expect_local()) {
680 self.reach(def_id, ctor_ev).ty();
681 }
682 }
683 }
684 }
685 DefKind::Struct | DefKind::Union => {
686 let def = self.tcx.adt_def(def_id).non_enum_variant();
687 if let Some(item_ev) = item_ev {
688 self.reach(def_id, item_ev).generics().predicates();
689 for field in &def.fields {
690 let field = field.did.expect_local();
691 self.update(field, item_ev, Level::Reachable);
692 if let Some(field_ev) = self.get(field) {
693 self.reach(field, field_ev).ty();
694 }
695 }
696 }
697 if let Some(ctor_def_id) = def.ctor_def_id() {
698 if let Some(item_ev) = item_ev {
699 self.update(ctor_def_id.expect_local(), item_ev, Level::Reachable);
700 }
701 if let Some(ctor_ev) = self.get(ctor_def_id.expect_local()) {
702 self.reach(def_id, ctor_ev).ty();
703 }
704 }
705 }
706 DefKind::ForeignMod => {}
708 DefKind::Field
709 | DefKind::Variant
710 | DefKind::AssocFn
711 | DefKind::AssocTy
712 | DefKind::AssocConst { .. }
713 | DefKind::TyParam
714 | DefKind::AnonConst
715 | DefKind::InlineConst
716 | DefKind::OpaqueTy
717 | DefKind::Closure
718 | DefKind::SyntheticCoroutineBody
719 | DefKind::ConstParam
720 | DefKind::LifetimeParam
721 | DefKind::Ctor(..) => {
722 ::rustc_middle::util::bug::span_bug_fmt(self.tcx.def_span(def_id),
format_args!("{0:?} should be checked while checking parent", def_kind))span_bug!(
723 self.tcx.def_span(def_id),
724 "{def_kind:?} should be checked while checking parent"
725 )
726 }
727 }
728 }
729}
730
731impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
732 fn generics(&mut self) -> &mut Self {
733 for param in &self.ev.tcx.generics_of(self.item_def_id).own_params {
734 if let GenericParamDefKind::Const { .. } = param.kind {
735 self.visit(
736 self.ev.tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip(),
737 );
738 }
739 if let Some(default) = param.default_value(self.ev.tcx) {
740 self.visit(default.instantiate_identity().skip_norm_wip());
741 }
742 }
743 self
744 }
745
746 fn predicates(&mut self) -> &mut Self {
747 self.visit_predicates(self.ev.tcx.explicit_predicates_of(self.item_def_id));
748 self
749 }
750
751 fn bounds(&mut self) -> &mut Self {
752 self.visit_clauses(self.ev.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
753 self
754 }
755
756 fn ty(&mut self) -> &mut Self {
757 self.visit(self.ev.tcx.type_of(self.item_def_id).instantiate_identity().skip_norm_wip());
758 self
759 }
760
761 fn trait_ref(&mut self) -> &mut Self {
762 self.visit_trait(
763 self.ev.tcx.impl_trait_ref(self.item_def_id).instantiate_identity().skip_norm_wip(),
764 );
765 self
766 }
767
768 fn enqueue_def_id(&mut self, def_id: LocalDefId) {
771 let def_kind = self.ev.tcx.def_kind(def_id);
772 match def_kind {
773 DefKind::Enum
774 | DefKind::Union
775 | DefKind::Struct
776 | DefKind::ForeignTy
777 | DefKind::Trait => {
778 self.ev.queue.insert(def_id);
779 if let Some(impls) = self.ev.def_ids_to_impls.get(&def_id) {
781 #[allow(rustc::potential_query_instability)]
783 self.ev.queue.extend(impls);
784 }
785 }
786
787 DefKind::TraitAlias | DefKind::Fn | DefKind::TyAlias => {
788 self.ev.queue.insert(def_id);
789 }
790
791 DefKind::AssocConst { .. } | DefKind::AssocFn | DefKind::AssocTy => {
792 self.ev.queue.insert(self.ev.tcx.local_parent(def_id));
794 }
795
796 DefKind::Ctor(ctor_of, _) => {
797 let update_id = match ctor_of {
798 CtorOf::Struct => self.ev.tcx.local_parent(def_id),
799 CtorOf::Variant => self.ev.tcx.local_parent(self.ev.tcx.local_parent(def_id)),
800 };
801 self.ev.queue.insert(update_id);
803 }
804
805 DefKind::Closure => {}
808
809 DefKind::Impl { .. }
811 | DefKind::Field
812 | DefKind::Variant
813 | DefKind::Static { .. }
814 | DefKind::Macro(_)
815 | DefKind::TyParam
816 | DefKind::AnonConst
817 | DefKind::InlineConst
818 | DefKind::OpaqueTy
819 | DefKind::SyntheticCoroutineBody
820 | DefKind::ConstParam
821 | DefKind::LifetimeParam
822 | DefKind::Mod
823 | DefKind::Use
824 | DefKind::ExternCrate
825 | DefKind::GlobalAsm
826 | DefKind::ForeignMod
827 | DefKind::Const { .. } => {
828 ::rustc_middle::util::bug::span_bug_fmt(self.tcx().def_span(def_id),
format_args!("{0:?} unexpectedly reached by `ReachEverythingInTheInterfaceVisitor`",
def_kind))span_bug!(
829 self.tcx().def_span(def_id),
830 "{def_kind:?} unexpectedly reached by `ReachEverythingInTheInterfaceVisitor`"
831 )
832 }
833 }
834 }
835}
836
837impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
838 fn tcx(&self) -> TyCtxt<'tcx> {
839 self.ev.tcx
840 }
841 fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
842 if let Some(def_id) = def_id.as_local() {
843 let max_vis = (self.level != Level::ReachableThroughImplTrait)
851 .then(|| self.ev.tcx.local_visibility(def_id));
852 if self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level) {
853 self.enqueue_def_id(def_id);
854 }
855 }
856 }
857}
858
859pub struct TestReachabilityVisitor<'a, 'tcx> {
861 tcx: TyCtxt<'tcx>,
862 effective_visibilities: &'a EffectiveVisibilities,
863}
864
865impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
866 fn effective_visibility_diagnostic(&self, def_id: LocalDefId) {
867 if {
{
'done:
{
for i in
::rustc_hir::attrs::HasAttrs::get_attrs(def_id, &self.tcx) {
#[allow(unused_imports)]
use rustc_hir::attrs::AttributeKind::*;
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(RustcEffectiveVisibility) => {
break 'done Some(());
}
rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(self.tcx, def_id, RustcEffectiveVisibility) {
868 let mut error_msg = String::new();
869 let span = self.tcx.def_span(def_id.to_def_id());
870 if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) {
871 for level in Level::all_levels() {
872 let vis_str = effective_vis.at_level(level).to_string(def_id, self.tcx);
873 if level != Level::Direct {
874 error_msg.push_str(", ");
875 }
876 error_msg.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}: {1}", level, vis_str))
})format!("{level:?}: {vis_str}"));
877 }
878 } else {
879 error_msg.push_str("not in the table");
880 }
881 self.tcx.dcx().emit_err(ReportEffectiveVisibility { span, descr: error_msg });
882 }
883 }
884}
885
886impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
887 fn check_def_id(&self, owner_id: OwnerId) {
888 self.effective_visibility_diagnostic(owner_id.def_id);
889
890 match self.tcx.def_kind(owner_id) {
891 DefKind::Enum => {
892 let def = self.tcx.adt_def(owner_id.def_id);
893 for variant in def.variants() {
894 self.effective_visibility_diagnostic(variant.def_id.expect_local());
895 if let Some(ctor_def_id) = variant.ctor_def_id() {
896 self.effective_visibility_diagnostic(ctor_def_id.expect_local());
897 }
898 for field in &variant.fields {
899 self.effective_visibility_diagnostic(field.did.expect_local());
900 }
901 }
902 }
903 DefKind::Struct | DefKind::Union => {
904 let def = self.tcx.adt_def(owner_id.def_id).non_enum_variant();
905 if let Some(ctor_def_id) = def.ctor_def_id() {
906 self.effective_visibility_diagnostic(ctor_def_id.expect_local());
907 }
908 for field in &def.fields {
909 self.effective_visibility_diagnostic(field.did.expect_local());
910 }
911 }
912 _ => {}
913 }
914 }
915}
916
917struct NamePrivacyVisitor<'tcx> {
923 tcx: TyCtxt<'tcx>,
924 maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
925}
926
927impl<'tcx> NamePrivacyVisitor<'tcx> {
928 #[track_caller]
932 fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
933 self.maybe_typeck_results
934 .expect("`NamePrivacyVisitor::typeck_results` called outside of body")
935 }
936
937 fn check_field(
939 &self,
940 hir_id: hir::HirId, use_ctxt: Span, def: ty::AdtDef<'tcx>, field: &'tcx ty::FieldDef,
944 ) -> bool {
945 if def.is_enum() {
946 return true;
947 }
948
949 let ident = Ident::new(sym::dummy, use_ctxt);
951 let (_, def_id) =
952 self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id.owner.def_id);
953 !field.vis.is_accessible_from(def_id, self.tcx)
954 }
955
956 fn emit_unreachable_field_error(
958 &self,
959 fields: Vec<(Symbol, Span, bool )>,
960 def: ty::AdtDef<'tcx>, update_syntax: Option<Span>,
962 struct_span: Span,
963 ) {
964 if def.is_enum() || fields.is_empty() {
965 return;
966 }
967
968 let Some(field_names) = listify(&fields[..], |(n, _, _)| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", n))
})format!("`{n}`")) else { return };
980 let span: MultiSpan = fields.iter().map(|(_, span, _)| *span).collect::<Vec<Span>>().into();
981
982 let rest_field_names: Vec<_> =
984 fields.iter().filter(|(_, _, is_present)| !is_present).map(|(n, _, _)| n).collect();
985 let rest_len = rest_field_names.len();
986 let rest_field_names =
987 listify(&rest_field_names[..], |n| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", n))
})format!("`{n}`")).unwrap_or_default();
988 let labels = fields
990 .iter()
991 .filter(|(_, _, is_present)| *is_present)
992 .map(|(_, span, _)| FieldIsPrivateLabel::Other { span: *span })
993 .chain(update_syntax.iter().map(|span| FieldIsPrivateLabel::IsUpdateSyntax {
994 span: *span,
995 rest_field_names: rest_field_names.clone(),
996 rest_len,
997 }))
998 .collect();
999
1000 self.tcx.dcx().emit_err(FieldIsPrivate {
1001 span,
1002 struct_span: if self
1003 .tcx
1004 .sess
1005 .source_map()
1006 .is_multiline(fields[0].1.between(struct_span))
1007 {
1008 Some(struct_span)
1009 } else {
1010 None
1011 },
1012 field_names,
1013 variant_descr: def.variant_descr(),
1014 def_path_str: self.tcx.def_path_str(def.did()),
1015 labels,
1016 len: fields.len(),
1017 });
1018 }
1019
1020 fn check_expanded_fields(
1021 &self,
1022 adt: ty::AdtDef<'tcx>,
1023 variant: &'tcx ty::VariantDef,
1024 fields: &[hir::ExprField<'tcx>],
1025 hir_id: hir::HirId,
1026 span: Span,
1027 struct_span: Span,
1028 ) {
1029 let mut failed_fields = ::alloc::vec::Vec::new()vec![];
1030 for (vf_index, variant_field) in variant.fields.iter_enumerated() {
1031 let field =
1032 fields.iter().find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
1033 let (hir_id, use_ctxt, span) = match field {
1034 Some(field) => (field.hir_id, field.ident.span, field.span),
1035 None => (hir_id, span, span),
1036 };
1037 if self.check_field(hir_id, use_ctxt, adt, variant_field) {
1038 let name = match field {
1039 Some(field) => field.ident.name,
1040 None => variant_field.name,
1041 };
1042 failed_fields.push((name, span, field.is_some()));
1043 }
1044 }
1045 self.emit_unreachable_field_error(failed_fields, adt, Some(span), struct_span);
1046 }
1047}
1048
1049impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
1050 fn visit_nested_body(&mut self, body_id: hir::BodyId) {
1051 let new_typeck_results = self.tcx.typeck_body(body_id);
1052 if new_typeck_results.tainted_by_errors.is_some() {
1054 return;
1055 }
1056 let old_maybe_typeck_results = self.maybe_typeck_results.replace(new_typeck_results);
1057 self.visit_body(self.tcx.hir_body(body_id));
1058 self.maybe_typeck_results = old_maybe_typeck_results;
1059 }
1060
1061 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
1062 if let hir::ExprKind::Struct(qpath, fields, ref base) = expr.kind {
1063 let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
1064 let adt = self.typeck_results().expr_ty(expr).ty_adt_def().unwrap();
1065 let variant = adt.variant_of_res(res);
1066 match *base {
1067 hir::StructTailExpr::Base(base) => {
1068 self.check_expanded_fields(
1072 adt,
1073 variant,
1074 fields,
1075 base.hir_id,
1076 base.span,
1077 qpath.span(),
1078 );
1079 }
1080 hir::StructTailExpr::DefaultFields(span) => {
1081 self.check_expanded_fields(
1082 adt,
1083 variant,
1084 fields,
1085 expr.hir_id,
1086 span,
1087 qpath.span(),
1088 );
1089 }
1090 hir::StructTailExpr::None | hir::StructTailExpr::NoneWithError(_) => {
1091 let mut failed_fields = ::alloc::vec::Vec::new()vec![];
1092 for field in fields {
1093 let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
1094 let index = self.typeck_results().field_index(field.hir_id);
1095 if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
1096 failed_fields.push((field.ident.name, field.ident.span, true));
1097 }
1098 }
1099 self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
1100 }
1101 }
1102 }
1103
1104 intravisit::walk_expr(self, expr);
1105 }
1106
1107 fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
1108 if let PatKind::Struct(ref qpath, fields, _) = pat.kind {
1109 let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
1110 let adt = self.typeck_results().pat_ty(pat).ty_adt_def().unwrap();
1111 let variant = adt.variant_of_res(res);
1112 let mut failed_fields = ::alloc::vec::Vec::new()vec![];
1113 for field in fields {
1114 let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
1115 let index = self.typeck_results().field_index(field.hir_id);
1116 if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
1117 failed_fields.push((field.ident.name, field.ident.span, true));
1118 }
1119 }
1120 self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
1121 }
1122
1123 intravisit::walk_pat(self, pat);
1124 }
1125}
1126
1127struct TypePrivacyVisitor<'tcx> {
1132 tcx: TyCtxt<'tcx>,
1133 module_def_id: LocalModDefId,
1134 maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
1135 span: Span,
1136}
1137
1138impl<'tcx> TypePrivacyVisitor<'tcx> {
1139 fn item_is_accessible(&self, did: DefId) -> bool {
1140 self.tcx.visibility(did).is_accessible_from(self.module_def_id, self.tcx)
1141 }
1142
1143 fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
1145 self.span = span;
1146 let typeck_results = self
1147 .maybe_typeck_results
1148 .unwrap_or_else(|| ::rustc_middle::util::bug::span_bug_fmt(span,
format_args!("`hir::Expr` or `hir::Pat` outside of a body"))span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body"));
1149 try {
1150 self.visit(typeck_results.node_type(id))?;
1151 self.visit(typeck_results.node_args(id))?;
1152 if let Some(adjustments) = typeck_results.adjustments().get(id) {
1153 adjustments.iter().try_for_each(|adjustment| self.visit(adjustment.target))?;
1154 }
1155 }
1156 .is_break()
1157 }
1158
1159 fn check_def_id(&self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1160 let is_error = !self.item_is_accessible(def_id);
1161 if is_error {
1162 self.tcx.dcx().emit_err(ItemIsPrivate { span: self.span, kind, descr: descr.into() });
1163 }
1164 is_error
1165 }
1166}
1167
1168impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
1169 type Result = ControlFlow<()>;
1170 fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
1171 self.span = span;
1172 value.visit_with(&mut self.skeleton())
1173 }
1174}
1175
1176impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
1177 fn visit_nested_body(&mut self, body_id: hir::BodyId) {
1178 let old_maybe_typeck_results =
1179 self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
1180 self.visit_body(self.tcx.hir_body(body_id));
1181 self.maybe_typeck_results = old_maybe_typeck_results;
1182 }
1183
1184 fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
1185 self.span = hir_ty.span;
1186 if self
1187 .visit(
1188 self.maybe_typeck_results
1189 .unwrap_or_else(|| ::rustc_middle::util::bug::span_bug_fmt(hir_ty.span,
format_args!("`hir::Ty` outside of a body"))span_bug!(hir_ty.span, "`hir::Ty` outside of a body"))
1190 .node_type(hir_ty.hir_id),
1191 )
1192 .is_break()
1193 {
1194 return;
1195 }
1196
1197 intravisit::walk_ty(self, hir_ty);
1198 }
1199
1200 fn visit_infer(
1201 &mut self,
1202 inf_id: rustc_hir::HirId,
1203 inf_span: Span,
1204 _kind: InferKind<'tcx>,
1205 ) -> Self::Result {
1206 self.span = inf_span;
1207 if let Some(ty) = self
1208 .maybe_typeck_results
1209 .unwrap_or_else(|| ::rustc_middle::util::bug::span_bug_fmt(inf_span,
format_args!("Inference variable outside of a body"))span_bug!(inf_span, "Inference variable outside of a body"))
1210 .node_type_opt(inf_id)
1211 {
1212 if self.visit(ty).is_break() {
1213 return;
1214 }
1215 } else {
1216 }
1218
1219 self.visit_id(inf_id)
1220 }
1221
1222 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
1224 if self.check_expr_pat_type(expr.hir_id, expr.span) {
1225 return;
1227 }
1228 match expr.kind {
1229 hir::ExprKind::Assign(_, rhs, _) | hir::ExprKind::Match(rhs, ..) => {
1230 if self.check_expr_pat_type(rhs.hir_id, rhs.span) {
1232 return;
1233 }
1234 }
1235 hir::ExprKind::MethodCall(segment, ..) => {
1236 self.span = segment.ident.span;
1238 let typeck_results = self
1239 .maybe_typeck_results
1240 .unwrap_or_else(|| ::rustc_middle::util::bug::span_bug_fmt(self.span,
format_args!("`hir::Expr` outside of a body"))span_bug!(self.span, "`hir::Expr` outside of a body"));
1241 if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
1242 if self
1243 .visit(self.tcx.type_of(def_id).instantiate_identity().skip_norm_wip())
1244 .is_break()
1245 {
1246 return;
1247 }
1248 } else {
1249 self.tcx
1250 .dcx()
1251 .span_delayed_bug(expr.span, "no type-dependent def for method call");
1252 }
1253 }
1254 _ => {}
1255 }
1256
1257 intravisit::walk_expr(self, expr);
1258 }
1259
1260 fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: Span) {
1267 let def = match qpath {
1268 hir::QPath::Resolved(_, path) => match path.res {
1269 Res::Def(kind, def_id) => Some((kind, def_id)),
1270 _ => None,
1271 },
1272 hir::QPath::TypeRelative(..) => {
1273 match self.maybe_typeck_results {
1274 Some(typeck_results) => typeck_results.type_dependent_def(id),
1275 None => None,
1277 }
1278 }
1279 };
1280 let def = def.filter(|(kind, _)| {
1281 #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::AssocFn | DefKind::AssocConst { .. } | DefKind::AssocTy |
DefKind::Static { .. } => true,
_ => false,
}matches!(
1282 kind,
1283 DefKind::AssocFn
1284 | DefKind::AssocConst { .. }
1285 | DefKind::AssocTy
1286 | DefKind::Static { .. }
1287 )
1288 });
1289 if let Some((kind, def_id)) = def {
1290 let is_local_static =
1291 if let DefKind::Static { .. } = kind { def_id.is_local() } else { false };
1292 if !self.item_is_accessible(def_id) && !is_local_static {
1293 let name = match *qpath {
1294 hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
1295 hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
1296 };
1297 let kind = self.tcx.def_descr(def_id);
1298 let sess = self.tcx.sess;
1299 let _ = match name {
1300 Some(name) => {
1301 sess.dcx().emit_err(ItemIsPrivate { span, kind, descr: (&name).into() })
1302 }
1303 None => sess.dcx().emit_err(UnnamedItemIsPrivate { span, kind }),
1304 };
1305 return;
1306 }
1307 }
1308
1309 intravisit::walk_qpath(self, qpath, id);
1310 }
1311
1312 fn visit_pat(&mut self, pattern: &'tcx hir::Pat<'tcx>) {
1314 if self.check_expr_pat_type(pattern.hir_id, pattern.span) {
1315 return;
1317 }
1318
1319 intravisit::walk_pat(self, pattern);
1320 }
1321
1322 fn visit_local(&mut self, local: &'tcx hir::LetStmt<'tcx>) {
1323 if let Some(init) = local.init {
1324 if self.check_expr_pat_type(init.hir_id, init.span) {
1325 return;
1327 }
1328 }
1329
1330 intravisit::walk_local(self, local);
1331 }
1332}
1333
1334impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
1335 type Result = ControlFlow<()>;
1336 fn tcx(&self) -> TyCtxt<'tcx> {
1337 self.tcx
1338 }
1339 fn visit_def_id(
1340 &mut self,
1341 def_id: DefId,
1342 kind: &str,
1343 descr: &dyn fmt::Display,
1344 ) -> Self::Result {
1345 if self.check_def_id(def_id, kind, descr) {
1346 ControlFlow::Break(())
1347 } else {
1348 ControlFlow::Continue(())
1349 }
1350 }
1351}
1352
1353struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
1359 tcx: TyCtxt<'tcx>,
1360 item_def_id: LocalDefId,
1361 required_visibility: ty::Visibility,
1363 required_effective_vis: Option<EffectiveVisibility>,
1364 hard_error: bool = false,
1365 in_primary_interface: bool = true,
1366 skip_assoc_tys: bool = false,
1367}
1368
1369impl SearchInterfaceForPrivateItemsVisitor<'_> {
1370 fn generics(&mut self) -> &mut Self {
1371 self.in_primary_interface = true;
1372 for param in &self.tcx.generics_of(self.item_def_id).own_params {
1373 if let GenericParamDefKind::Const { .. } = param.kind {
1374 let _ = self
1375 .visit(self.tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip());
1376 }
1377 if let Some(default) = param.default_value(self.tcx) {
1378 let _ = self.visit(default.instantiate_identity().skip_norm_wip());
1379 }
1380 }
1381 self
1382 }
1383
1384 fn predicates(&mut self) -> &mut Self {
1385 self.in_primary_interface = false;
1386 let _ = self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id));
1393 self
1394 }
1395
1396 fn bounds(&mut self) -> &mut Self {
1397 self.in_primary_interface = false;
1398 let _ = self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
1399 self
1400 }
1401
1402 fn ty(&mut self) -> &mut Self {
1403 self.in_primary_interface = true;
1404 let _ =
1405 self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity().skip_norm_wip());
1406 self
1407 }
1408
1409 fn trait_ref(&mut self) -> &mut Self {
1410 self.in_primary_interface = true;
1411 let _ = self.visit_trait(
1412 self.tcx.impl_trait_ref(self.item_def_id).instantiate_identity().skip_norm_wip(),
1413 );
1414 self
1415 }
1416
1417 fn check_def_id(&self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1418 if self.leaks_private_dep(def_id) {
1419 self.tcx.emit_node_span_lint(
1420 lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
1421 self.tcx.local_def_id_to_hir_id(self.item_def_id),
1422 self.tcx.def_span(self.item_def_id.to_def_id()),
1423 FromPrivateDependencyInPublicInterface {
1424 kind,
1425 descr: descr.into(),
1426 krate: self.tcx.crate_name(def_id.krate),
1427 },
1428 );
1429 }
1430
1431 let Some(local_def_id) = def_id.as_local() else {
1432 return false;
1433 };
1434
1435 let vis = self.tcx.local_visibility(local_def_id);
1436 if self.hard_error && self.required_visibility.greater_than(vis, self.tcx) {
1437 let vis_descr = match vis {
1438 ty::Visibility::Public => "public",
1439 ty::Visibility::Restricted(vis_def_id) => {
1440 if vis_def_id
1441 == self.tcx.parent_module_from_def_id(local_def_id).to_local_def_id()
1442 {
1443 "private"
1444 } else if vis_def_id.is_top_level_module() {
1445 "crate-private"
1446 } else {
1447 "restricted"
1448 }
1449 }
1450 };
1451
1452 let span = self.tcx.def_span(self.item_def_id.to_def_id());
1453 let vis_span = self.tcx.def_span(def_id);
1454 self.tcx.dcx().emit_err(InPublicInterface {
1455 span,
1456 vis_descr,
1457 kind,
1458 descr: descr.into(),
1459 vis_span,
1460 });
1461 return false;
1462 }
1463
1464 let Some(effective_vis) = self.required_effective_vis else {
1465 return false;
1466 };
1467
1468 let reachable_at_vis = *effective_vis.at_level(Level::Reachable);
1469
1470 if reachable_at_vis.greater_than(vis, self.tcx) {
1471 let lint = if self.in_primary_interface {
1472 lint::builtin::PRIVATE_INTERFACES
1473 } else {
1474 lint::builtin::PRIVATE_BOUNDS
1475 };
1476 let span = self.tcx.def_span(self.item_def_id.to_def_id());
1477 let vis_span = self.tcx.def_span(def_id);
1478 self.tcx.emit_node_span_lint(
1479 lint,
1480 self.tcx.local_def_id_to_hir_id(self.item_def_id),
1481 span,
1482 PrivateInterfacesOrBoundsLint {
1483 item_span: span,
1484 item_kind: self.tcx.def_descr(self.item_def_id.to_def_id()),
1485 item_descr: (&LazyDefPathStr {
1486 def_id: self.item_def_id.to_def_id(),
1487 tcx: self.tcx,
1488 })
1489 .into(),
1490 item_vis_descr: &reachable_at_vis.to_string(self.item_def_id, self.tcx),
1491 ty_span: vis_span,
1492 ty_kind: kind,
1493 ty_descr: descr.into(),
1494 ty_vis_descr: &vis.to_string(local_def_id, self.tcx),
1495 },
1496 );
1497 }
1498
1499 false
1500 }
1501
1502 fn leaks_private_dep(&self, item_id: DefId) -> bool {
1507 let ret = self.required_visibility.is_public() && self.tcx.is_private_dep(item_id.krate);
1508
1509 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_privacy/src/lib.rs:1509",
"rustc_privacy", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_privacy/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(1509u32),
::tracing_core::__macro_support::Option::Some("rustc_privacy"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("leaks_private_dep(item_id={0:?})={1}",
item_id, ret) as &dyn Value))])
});
} else { ; }
};debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
1510 ret
1511 }
1512}
1513
1514impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
1515 type Result = ControlFlow<()>;
1516 fn skip_assoc_tys(&self) -> bool {
1517 self.skip_assoc_tys
1518 }
1519 fn tcx(&self) -> TyCtxt<'tcx> {
1520 self.tcx
1521 }
1522 fn visit_def_id(
1523 &mut self,
1524 def_id: DefId,
1525 kind: &str,
1526 descr: &dyn fmt::Display,
1527 ) -> Self::Result {
1528 if self.check_def_id(def_id, kind, descr) {
1529 ControlFlow::Break(())
1530 } else {
1531 ControlFlow::Continue(())
1532 }
1533 }
1534}
1535
1536struct PrivateItemsInPublicInterfacesChecker<'a, 'tcx> {
1537 tcx: TyCtxt<'tcx>,
1538 effective_visibilities: &'a EffectiveVisibilities,
1539}
1540
1541impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
1542 fn check(
1543 &self,
1544 def_id: LocalDefId,
1545 required_visibility: ty::Visibility,
1546 required_effective_vis: Option<EffectiveVisibility>,
1547 ) -> SearchInterfaceForPrivateItemsVisitor<'tcx> {
1548 SearchInterfaceForPrivateItemsVisitor {
1549 tcx: self.tcx,
1550 item_def_id: def_id,
1551 required_visibility,
1552 required_effective_vis,
1553 ..
1554 }
1555 }
1556
1557 fn check_unnameable(&self, def_id: LocalDefId, effective_vis: Option<EffectiveVisibility>) {
1558 let Some(effective_vis) = effective_vis else {
1559 return;
1560 };
1561
1562 let reexported_at_vis = effective_vis.at_level(Level::Reexported);
1563 let reachable_at_vis = effective_vis.at_level(Level::Reachable);
1564
1565 if reachable_at_vis.is_public() && reexported_at_vis != reachable_at_vis {
1566 let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
1567 let span = self.tcx.def_span(def_id.to_def_id());
1568 self.tcx.emit_node_span_lint(
1569 lint::builtin::UNNAMEABLE_TYPES,
1570 hir_id,
1571 span,
1572 UnnameableTypesLint {
1573 span,
1574 kind: self.tcx.def_descr(def_id.to_def_id()),
1575 descr: (&LazyDefPathStr { def_id: def_id.to_def_id(), tcx: self.tcx }).into(),
1576 reachable_vis: &reachable_at_vis.to_string(def_id, self.tcx),
1577 reexported_vis: &reexported_at_vis.to_string(def_id, self.tcx),
1578 },
1579 );
1580 }
1581 }
1582
1583 fn check_assoc_item(
1584 &self,
1585 item: &ty::AssocItem,
1586 vis: ty::Visibility,
1587 effective_vis: Option<EffectiveVisibility>,
1588 ) {
1589 let mut check = self.check(item.def_id.expect_local(), vis, effective_vis);
1590
1591 let is_assoc_ty = item.is_type();
1592 check.hard_error = is_assoc_ty;
1593 check.generics().predicates();
1594 if assoc_has_type_of(self.tcx, item) {
1595 check.ty();
1596 }
1597 if is_assoc_ty && item.container == AssocContainer::Trait {
1598 check.hard_error = false;
1601 check.bounds();
1602 }
1603 }
1604
1605 fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
1606 self.effective_visibilities.effective_vis(def_id).copied()
1607 }
1608
1609 fn check_item(&self, id: ItemId) {
1610 let tcx = self.tcx;
1611 let def_id = id.owner_id.def_id;
1612 let item_visibility = tcx.local_visibility(def_id);
1613 let effective_vis = self.get(def_id);
1614 let def_kind = tcx.def_kind(def_id);
1615
1616 match def_kind {
1617 DefKind::Const { .. } | DefKind::Static { .. } | DefKind::Fn | DefKind::TyAlias => {
1618 if let DefKind::TyAlias = def_kind {
1619 self.check_unnameable(def_id, effective_vis);
1620 }
1621 self.check(def_id, item_visibility, effective_vis).generics().predicates().ty();
1622 }
1623 DefKind::OpaqueTy => {
1624 self.check(def_id, item_visibility, effective_vis).generics().bounds();
1627 }
1628 DefKind::Trait => {
1629 self.check_unnameable(def_id, effective_vis);
1630
1631 self.check(def_id, item_visibility, effective_vis).generics().predicates();
1632
1633 for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
1634 self.check_assoc_item(assoc_item, item_visibility, effective_vis);
1635 }
1636 }
1637 DefKind::TraitAlias => {
1638 self.check(def_id, item_visibility, effective_vis).generics().predicates();
1639 }
1640 DefKind::Enum => {
1641 self.check_unnameable(def_id, effective_vis);
1642 self.check(def_id, item_visibility, effective_vis).generics().predicates();
1643
1644 let adt = tcx.adt_def(id.owner_id);
1645 for field in adt.all_fields() {
1646 self.check(field.did.expect_local(), item_visibility, effective_vis).ty();
1647 }
1648 }
1649 DefKind::Struct | DefKind::Union => {
1651 self.check_unnameable(def_id, effective_vis);
1652 self.check(def_id, item_visibility, effective_vis).generics().predicates();
1653
1654 let adt = tcx.adt_def(id.owner_id);
1655 for field in adt.all_fields() {
1656 let visibility = min(item_visibility, field.vis.expect_local(), tcx);
1657 let field_ev = self.get(field.did.expect_local());
1658
1659 self.check(field.did.expect_local(), visibility, field_ev).ty();
1660 }
1661 }
1662 DefKind::ForeignMod => {}
1664 DefKind::Impl { of_trait } => {
1669 let impl_vis =
1670 ty::Visibility::of_impl::<false>(def_id, of_trait, tcx, &Default::default());
1671
1672 let impl_ev = EffectiveVisibility::of_impl::<false>(
1684 def_id,
1685 of_trait,
1686 tcx,
1687 self.effective_visibilities,
1688 );
1689
1690 let mut check = self.check(def_id, impl_vis, Some(impl_ev));
1691
1692 if !of_trait {
1695 check.generics().predicates();
1696 }
1697
1698 check.skip_assoc_tys = true;
1702 check.ty();
1703 if of_trait {
1704 check.trait_ref();
1705 }
1706
1707 for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
1708 let impl_item_vis = if !of_trait {
1709 min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx)
1710 } else {
1711 impl_vis
1712 };
1713
1714 let impl_item_ev = if !of_trait {
1715 self.get(assoc_item.def_id.expect_local())
1716 .map(|ev| ev.min(impl_ev, self.tcx))
1717 } else {
1718 Some(impl_ev)
1719 };
1720
1721 self.check_assoc_item(assoc_item, impl_item_vis, impl_item_ev);
1722 }
1723 }
1724 _ => {}
1725 }
1726 }
1727
1728 fn check_foreign_item(&self, id: ForeignItemId) {
1729 let tcx = self.tcx;
1730 let def_id = id.owner_id.def_id;
1731 let item_visibility = tcx.local_visibility(def_id);
1732 let effective_vis = self.get(def_id);
1733
1734 if let DefKind::ForeignTy = self.tcx.def_kind(def_id) {
1735 self.check_unnameable(def_id, effective_vis);
1736 }
1737
1738 self.check(def_id, item_visibility, effective_vis).generics().predicates().ty();
1739 }
1740}
1741
1742pub fn provide(providers: &mut Providers) {
1743 *providers = Providers {
1744 effective_visibilities,
1745 check_private_in_public,
1746 check_mod_privacy,
1747 ..*providers
1748 };
1749}
1750
1751fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
1752 let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None };
1754 tcx.hir_visit_item_likes_in_module(module_def_id, &mut visitor);
1755
1756 let span = tcx.def_span(module_def_id);
1759 let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span };
1760
1761 let module = tcx.hir_module_items(module_def_id);
1762 for def_id in module.definitions() {
1763 let _ = rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor);
1764
1765 if let Some(body_id) = tcx.hir_maybe_body_owned_by(def_id) {
1766 visitor.visit_nested_body(body_id.id());
1767 }
1768
1769 if let DefKind::Impl { of_trait: true } = tcx.def_kind(def_id) {
1770 let trait_ref = tcx.impl_trait_ref(def_id);
1771 let trait_ref = trait_ref.instantiate_identity().skip_norm_wip();
1772 visitor.span =
1773 tcx.hir_expect_item(def_id).expect_impl().of_trait.unwrap().trait_ref.path.span;
1774 let _ =
1775 visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path());
1776 }
1777 }
1778}
1779
1780fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
1781 let def_ids_to_impls = DefIdsToImplsCollector::collect(tcx);
1782
1783 let mut visitor = EmbargoVisitor {
1786 tcx,
1787 effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
1788 queue: Default::default(),
1789 def_ids_to_impls,
1790 };
1791
1792 visitor.effective_visibilities.check_invariants(tcx);
1793
1794 let impl_trait_pass = !tcx.sess.opts.actually_rustdoc;
1798 if impl_trait_pass {
1799 let krate = tcx.hir_crate_items(());
1802 for id in krate.opaques() {
1803 let opaque = tcx.hir_node_by_def_id(id).expect_opaque_ty();
1804 let should_visit = match opaque.origin {
1805 hir::OpaqueTyOrigin::FnReturn {
1806 parent,
1807 in_trait_or_impl: Some(hir::RpitContext::Trait),
1808 }
1809 | hir::OpaqueTyOrigin::AsyncFn {
1810 parent,
1811 in_trait_or_impl: Some(hir::RpitContext::Trait),
1812 } => match tcx.hir_node_by_def_id(parent).expect_trait_item().expect_fn().1 {
1813 hir::TraitFn::Required(_) => false,
1814 hir::TraitFn::Provided(..) => true,
1815 },
1816
1817 hir::OpaqueTyOrigin::FnReturn {
1820 in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
1821 ..
1822 }
1823 | hir::OpaqueTyOrigin::AsyncFn {
1824 in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
1825 ..
1826 }
1827 | hir::OpaqueTyOrigin::TyAlias { .. } => true,
1828 };
1829 if should_visit {
1830 let pub_ev = EffectiveVisibility::from_vis(ty::Visibility::Public);
1834 visitor
1835 .reach_through_impl_trait(opaque.def_id, pub_ev)
1836 .generics()
1837 .predicates()
1838 .ty();
1839 }
1840 }
1841
1842 visitor.queue.clear();
1843 }
1844
1845 for (&adt_def_id, macro_mods) in &tcx.resolutions(()).macro_reachable_adts {
1848 let struct_def = tcx.adt_def(adt_def_id);
1849 let Some(struct_ev) = visitor.effective_visibilities.effective_vis(adt_def_id).copied()
1850 else {
1851 continue;
1852 };
1853 for field in &struct_def.non_enum_variant().fields {
1854 let def_id = field.did.expect_local();
1855 let field_vis = tcx.local_visibility(def_id);
1856
1857 for ¯o_mod in macro_mods {
1858 if field_vis.is_accessible_from(macro_mod, tcx) {
1859 visitor.reach(def_id, struct_ev).ty();
1860 }
1861 }
1862 }
1863 }
1864
1865 let crate_items = tcx.hir_crate_items(());
1866 for id in crate_items.free_items() {
1867 visitor.check_def_id(id.owner_id.def_id);
1868 }
1869 for id in crate_items.foreign_items() {
1870 visitor.check_def_id(id.owner_id.def_id);
1871 }
1872 while let Some(def_id) = visitor.queue.pop() {
1873 visitor.check_def_id(def_id);
1874 }
1875 visitor.effective_visibilities.check_invariants(tcx);
1876
1877 let check_visitor =
1878 TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
1879 for id in crate_items.owners() {
1880 check_visitor.check_def_id(id);
1881 }
1882
1883 tcx.arena.alloc(visitor.effective_visibilities)
1884}
1885
1886fn check_private_in_public(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
1887 let effective_visibilities = tcx.effective_visibilities(());
1888 let checker = PrivateItemsInPublicInterfacesChecker { tcx, effective_visibilities };
1890
1891 let crate_items = tcx.hir_module_items(module_def_id);
1892 let _ = crate_items.par_items(|id| Ok(checker.check_item(id)));
1893 let _ = crate_items.par_foreign_items(|id| Ok(checker.check_foreign_item(id)));
1894}