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