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