1#![feature(associated_type_defaults)]
3#![feature(default_field_values)]
4#![feature(try_blocks)]
5mod errors;
8
9use std::fmt;
10use std::marker::PhantomData;
11use std::ops::ControlFlow;
12
13use errors::{
14 FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
15 ItemIsPrivate, PrivateInterfacesOrBoundsLint, ReportEffectiveVisibility, UnnameableTypesLint,
16 UnnamedItemIsPrivate,
17};
18use rustc_ast::MacroDef;
19use rustc_ast::visit::{VisitorResult, try_visit};
20use rustc_data_structures::fx::FxHashSet;
21use rustc_data_structures::intern::Interned;
22use rustc_errors::{MultiSpan, listify};
23use rustc_hir as hir;
24use rustc_hir::attrs::AttributeKind;
25use rustc_hir::def::{DefKind, Res};
26use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
27use rustc_hir::intravisit::{self, InferKind, Visitor};
28use rustc_hir::{AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind, find_attr};
29use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
30use rustc_middle::query::Providers;
31use rustc_middle::ty::print::PrintTraitRefExt as _;
32use rustc_middle::ty::{
33 self, AssocContainer, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable,
34 TypeVisitable, TypeVisitor,
35};
36use rustc_middle::{bug, span_bug};
37use rustc_session::lint;
38use rustc_span::hygiene::Transparency;
39use rustc_span::{Ident, Span, Symbol, sym};
40use tracing::debug;
41
42#[allow(non_upper_case_globals)]
#[doc(hidden)]
#[doc =
r" Auto-generated constants for type-checked references to Fluent messages."]
pub(crate) mod fluent_generated {
#[doc =
"Constant referring to Fluent message `privacy_field_is_private` from `privacy`"]
pub const privacy_field_is_private: rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_field_is_private"),
None);
#[doc =
"Constant referring to Fluent message `privacy_field_is_private.label` from `privacy`"]
pub const privacy_label: rustc_errors::SubdiagMessage =
rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
#[doc =
"Constant referring to Fluent message `privacy_field_is_private_is_update_syntax_label` from `privacy`"]
pub const privacy_field_is_private_is_update_syntax_label:
rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_field_is_private_is_update_syntax_label"),
None);
#[doc =
"Constant referring to Fluent message `privacy_field_is_private_label` from `privacy`"]
pub const privacy_field_is_private_label: rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_field_is_private_label"),
None);
#[doc =
"Constant referring to Fluent message `privacy_from_private_dep_in_public_interface` from `privacy`"]
pub const privacy_from_private_dep_in_public_interface:
rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_from_private_dep_in_public_interface"),
None);
#[doc =
"Constant referring to Fluent message `privacy_in_public_interface` from `privacy`"]
pub const privacy_in_public_interface: rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_in_public_interface"),
None);
#[doc =
"Constant referring to Fluent message `privacy_in_public_interface.visibility_label` from `privacy`"]
pub const privacy_visibility_label: rustc_errors::SubdiagMessage =
rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("visibility_label"));
#[doc =
"Constant referring to Fluent message `privacy_item_is_private` from `privacy`"]
pub const privacy_item_is_private: rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_item_is_private"),
None);
#[doc =
"Constant referring to Fluent message `privacy_private_interface_or_bounds_lint` from `privacy`"]
pub const privacy_private_interface_or_bounds_lint:
rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_private_interface_or_bounds_lint"),
None);
#[doc =
"Constant referring to Fluent message `privacy_private_interface_or_bounds_lint.item_label` from `privacy`"]
pub const privacy_item_label: rustc_errors::SubdiagMessage =
rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("item_label"));
#[doc =
"Constant referring to Fluent message `privacy_private_interface_or_bounds_lint.ty_note` from `privacy`"]
pub const privacy_ty_note: rustc_errors::SubdiagMessage =
rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("ty_note"));
#[doc =
"Constant referring to Fluent message `privacy_report_effective_visibility` from `privacy`"]
pub const privacy_report_effective_visibility: rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_report_effective_visibility"),
None);
#[doc =
"Constant referring to Fluent message `privacy_unnameable_types_lint` from `privacy`"]
pub const privacy_unnameable_types_lint: rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_unnameable_types_lint"),
None);
#[doc =
"Constant referring to Fluent message `privacy_unnamed_item_is_private` from `privacy`"]
pub const privacy_unnamed_item_is_private: rustc_errors::DiagMessage =
rustc_errors::DiagMessage::FluentIdentifier(std::borrow::Cow::Borrowed("privacy_unnamed_item_is_private"),
None);
#[doc =
r" Constants expected to exist by the diagnostic derive macros to use as default Fluent"]
#[doc = r" identifiers for different subdiagnostic kinds."]
pub mod _subdiag {
#[doc = r" Default for `#[help]`"]
pub const help: rustc_errors::SubdiagMessage =
rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("help"));
#[doc = r" Default for `#[note]`"]
pub const note: rustc_errors::SubdiagMessage =
rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("note"));
#[doc = r" Default for `#[warn]`"]
pub const warn: rustc_errors::SubdiagMessage =
rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("warn"));
#[doc = r" Default for `#[label]`"]
pub const label: rustc_errors::SubdiagMessage =
rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("label"));
#[doc = r" Default for `#[suggestion]`"]
pub const suggestion: rustc_errors::SubdiagMessage =
rustc_errors::SubdiagMessage::FluentAttr(std::borrow::Cow::Borrowed("suggestion"));
}
}rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
43
44struct LazyDefPathStr<'tcx> {
49 def_id: DefId,
50 tcx: TyCtxt<'tcx>,
51}
52
53impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55 f.write_fmt(format_args!("{0}", self.tcx.def_path_str(self.def_id)))write!(f, "{}", self.tcx.def_path_str(self.def_id))
56 }
57}
58
59pub trait DefIdVisitor<'tcx> {
68 type Result: VisitorResult = ();
69 const SHALLOW: bool = false;
70 fn skip_assoc_tys(&self) -> bool {
71 false
72 }
73
74 fn tcx(&self) -> TyCtxt<'tcx>;
75 fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
79 -> Self::Result;
80
81 fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
83 DefIdVisitorSkeleton {
84 def_id_visitor: self,
85 visited_tys: Default::default(),
86 dummy: Default::default(),
87 }
88 }
89 fn visit(&mut self, ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
90 ty_fragment.visit_with(&mut self.skeleton())
91 }
92 fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> Self::Result {
93 self.skeleton().visit_trait(trait_ref)
94 }
95 fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> Self::Result {
96 self.skeleton().visit_clauses(predicates.predicates)
97 }
98 fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result {
99 self.skeleton().visit_clauses(clauses)
100 }
101}
102
103pub struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
104 def_id_visitor: &'v mut V,
105 visited_tys: FxHashSet<Ty<'tcx>>,
106 dummy: PhantomData<TyCtxt<'tcx>>,
107}
108
109impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
110where
111 V: DefIdVisitor<'tcx> + ?Sized,
112{
113 fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result {
114 let TraitRef { def_id, args, .. } = trait_ref;
115 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(
116 def_id,
117 "trait",
118 &trait_ref.print_only_trait_path()
119 ));
120 if V::SHALLOW { V::Result::output() } else { args.visit_with(self) }
121 }
122
123 fn visit_projection_term(&mut self, projection: ty::AliasTerm<'tcx>) -> V::Result {
124 let tcx = self.def_id_visitor.tcx();
125 let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx);
126 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));
127 if V::SHALLOW {
128 V::Result::output()
129 } else {
130 V::Result::from_branch(
131 assoc_args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
132 )
133 }
134 }
135
136 fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result {
137 match clause.kind().skip_binder() {
138 ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
139 self.visit_trait(trait_ref)
140 }
141 ty::ClauseKind::HostEffect(pred) => {
142 match ::rustc_ast_ir::visit::VisitorResult::branch(self.visit_trait(pred.trait_ref))
{
core::ops::ControlFlow::Continue(()) =>
(),
#[allow(unreachable_code)]
core::ops::ControlFlow::Break(r) => {
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
}
};try_visit!(self.visit_trait(pred.trait_ref));
143 pred.constness.visit_with(self)
144 }
145 ty::ClauseKind::Projection(ty::ProjectionPredicate {
146 projection_term: projection_ty,
147 term,
148 }) => {
149 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));
150 self.visit_projection_term(projection_ty)
151 }
152 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
153 ty::ClauseKind::RegionOutlives(..) => V::Result::output(),
154 ty::ClauseKind::ConstArgHasType(ct, ty) => {
155 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));
156 ty.visit_with(self)
157 }
158 ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
159 ty::ClauseKind::WellFormed(term) => term.visit_with(self),
160 ty::ClauseKind::UnstableFeature(_) => V::Result::output(),
161 }
162 }
163
164 fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result {
165 for &(clause, _) in clauses {
166 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));
167 }
168 V::Result::output()
169 }
170}
171
172impl<'tcx, V> TypeVisitor<TyCtxt<'tcx>> for DefIdVisitorSkeleton<'_, 'tcx, V>
173where
174 V: DefIdVisitor<'tcx> + ?Sized,
175{
176 type Result = V::Result;
177
178 fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result {
179 self.visit_clause(p.as_clause().unwrap())
180 }
181
182 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
183 let tcx = self.def_id_visitor.tcx();
184 let ty_kind = *ty.kind();
187 match ty_kind {
188 ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), ..)
189 | ty::Foreign(def_id)
190 | ty::FnDef(def_id, ..)
191 | ty::Closure(def_id, ..)
192 | ty::CoroutineClosure(def_id, ..)
193 | ty::Coroutine(def_id, ..) => {
194 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));
195 if V::SHALLOW {
196 return V::Result::output();
197 }
198 if let ty::FnDef(..) = ty_kind {
202 match ::rustc_ast_ir::visit::VisitorResult::branch(tcx.fn_sig(def_id).instantiate_identity().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!(tcx.fn_sig(def_id).instantiate_identity().visit_with(self));
204 }
205 if let Some(assoc_item) = tcx.opt_associated_item(def_id)
210 && let Some(impl_def_id) = assoc_item.impl_container(tcx)
211 {
212 match ::rustc_ast_ir::visit::VisitorResult::branch(tcx.type_of(impl_def_id).instantiate_identity().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!(tcx.type_of(impl_def_id).instantiate_identity().visit_with(self));
213 }
214 }
215 ty::Alias(kind @ (ty::Inherent | ty::Free | ty::Projection), data) => {
216 if self.def_id_visitor.skip_assoc_tys() {
217 return V::Result::output();
223 }
224 if !self.visited_tys.insert(ty) {
225 return V::Result::output();
229 }
230
231 match ::rustc_ast_ir::visit::VisitorResult::branch(self.def_id_visitor.visit_def_id(data.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: data.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(
232 data.def_id,
233 match kind {
234 ty::Inherent | ty::Projection => "associated type",
235 ty::Free => "type alias",
236 ty::Opaque => unreachable!(),
237 },
238 &LazyDefPathStr { def_id: data.def_id, tcx },
239 ));
240
241 return if V::SHALLOW {
243 V::Result::output()
244 } else if kind == ty::Projection {
245 self.visit_projection_term(data.into())
246 } else {
247 V::Result::from_branch(
248 data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
249 )
250 };
251 }
252 ty::Dynamic(predicates, ..) => {
253 for predicate in predicates {
256 let trait_ref = match predicate.skip_binder() {
257 ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
258 ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
259 ty::ExistentialPredicate::AutoTrait(def_id) => {
260 ty::ExistentialTraitRef::new(tcx, def_id, ty::GenericArgs::empty())
261 }
262 };
263 let ty::ExistentialTraitRef { def_id, .. } = trait_ref;
264 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));
265 }
266 }
267 ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
268 if self.visited_tys.insert(ty) {
270 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()));
278 }
279 }
280 ty::Bool
283 | ty::Char
284 | ty::Int(..)
285 | ty::Uint(..)
286 | ty::Float(..)
287 | ty::Str
288 | ty::Never
289 | ty::Array(..)
290 | ty::Slice(..)
291 | ty::Tuple(..)
292 | ty::RawPtr(..)
293 | ty::Ref(..)
294 | ty::Pat(..)
295 | ty::FnPtr(..)
296 | ty::UnsafeBinder(_)
297 | ty::Param(..)
298 | ty::Bound(..)
299 | ty::Error(_)
300 | ty::CoroutineWitness(..) => {}
301 ty::Placeholder(..) | ty::Infer(..) => {
302 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected type: {0:?}", ty))bug!("unexpected type: {:?}", ty)
303 }
304 }
305
306 if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) }
307 }
308
309 fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
310 let tcx = self.def_id_visitor.tcx();
311 tcx.expand_abstract_consts(c).super_visit_with(self)
312 }
313}
314
315fn assoc_has_type_of(tcx: TyCtxt<'_>, item: &ty::AssocItem) -> bool {
316 if let ty::AssocKind::Type { data: ty::AssocTypeData::Normal(..) } = item.kind
317 && let hir::Node::TraitItem(item) =
318 tcx.hir_node(tcx.local_def_id_to_hir_id(item.def_id.expect_local()))
319 && let hir::TraitItemKind::Type(_, None) = item.kind
320 {
321 false
322 } else {
323 true
324 }
325}
326
327fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
328 if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
329}
330
331struct FindMin<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> {
333 tcx: TyCtxt<'tcx>,
334 effective_visibilities: &'a EffectiveVisibilities,
335 min: VL,
336}
337
338impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
339 for FindMin<'a, 'tcx, VL, SHALLOW>
340{
341 const SHALLOW: bool = SHALLOW;
342 fn skip_assoc_tys(&self) -> bool {
343 true
344 }
345 fn tcx(&self) -> TyCtxt<'tcx> {
346 self.tcx
347 }
348 fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
349 if let Some(def_id) = def_id.as_local() {
350 self.min = VL::new_min(self, def_id);
351 }
352 }
353}
354
355trait VisibilityLike: Sized {
356 const MAX: Self;
357 fn new_min<const SHALLOW: bool>(
358 find: &FindMin<'_, '_, Self, SHALLOW>,
359 def_id: LocalDefId,
360 ) -> Self;
361
362 fn of_impl<const SHALLOW: bool>(
365 def_id: LocalDefId,
366 of_trait: bool,
367 tcx: TyCtxt<'_>,
368 effective_visibilities: &EffectiveVisibilities,
369 ) -> Self {
370 let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
371 find.visit(tcx.type_of(def_id).instantiate_identity());
372 if of_trait {
373 find.visit_trait(tcx.impl_trait_ref(def_id).instantiate_identity());
374 }
375 find.min
376 }
377}
378
379impl VisibilityLike for ty::Visibility {
380 const MAX: Self = ty::Visibility::Public;
381 fn new_min<const SHALLOW: bool>(
382 find: &FindMin<'_, '_, Self, SHALLOW>,
383 def_id: LocalDefId,
384 ) -> Self {
385 min(find.tcx.local_visibility(def_id), find.min, find.tcx)
386 }
387}
388
389impl VisibilityLike for EffectiveVisibility {
390 const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public);
391 fn new_min<const SHALLOW: bool>(
392 find: &FindMin<'_, '_, Self, SHALLOW>,
393 def_id: LocalDefId,
394 ) -> Self {
395 let effective_vis =
396 find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| {
397 let private_vis = ty::Visibility::Restricted(
398 find.tcx.parent_module_from_def_id(def_id).to_local_def_id(),
399 );
400 EffectiveVisibility::from_vis(private_vis)
401 });
402
403 effective_vis.min(find.min, find.tcx)
404 }
405}
406
407struct EmbargoVisitor<'tcx> {
409 tcx: TyCtxt<'tcx>,
410
411 effective_visibilities: EffectiveVisibilities,
413 macro_reachable: FxHashSet<(LocalModDefId, LocalModDefId)>,
426 changed: bool,
428}
429
430struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
431 effective_vis: EffectiveVisibility,
432 item_def_id: LocalDefId,
433 ev: &'a mut EmbargoVisitor<'tcx>,
434 level: Level,
435}
436
437impl<'tcx> EmbargoVisitor<'tcx> {
438 fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
439 self.effective_visibilities.effective_vis(def_id).copied()
440 }
441
442 fn update(
444 &mut self,
445 def_id: LocalDefId,
446 inherited_effective_vis: EffectiveVisibility,
447 level: Level,
448 ) {
449 let nominal_vis = self.tcx.local_visibility(def_id);
450 self.update_eff_vis(def_id, inherited_effective_vis, Some(nominal_vis), level);
451 }
452
453 fn update_eff_vis(
454 &mut self,
455 def_id: LocalDefId,
456 inherited_effective_vis: EffectiveVisibility,
457 max_vis: Option<ty::Visibility>,
458 level: Level,
459 ) {
460 let private_vis =
462 ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id).into());
463 if max_vis != Some(private_vis) {
464 self.changed |= self.effective_visibilities.update(
465 def_id,
466 max_vis,
467 || private_vis,
468 inherited_effective_vis,
469 level,
470 self.tcx,
471 );
472 }
473 }
474
475 fn reach(
476 &mut self,
477 def_id: LocalDefId,
478 effective_vis: EffectiveVisibility,
479 ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
480 ReachEverythingInTheInterfaceVisitor {
481 effective_vis,
482 item_def_id: def_id,
483 ev: self,
484 level: Level::Reachable,
485 }
486 }
487
488 fn reach_through_impl_trait(
489 &mut self,
490 def_id: LocalDefId,
491 effective_vis: EffectiveVisibility,
492 ) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
493 ReachEverythingInTheInterfaceVisitor {
494 effective_vis,
495 item_def_id: def_id,
496 ev: self,
497 level: Level::ReachableThroughImplTrait,
498 }
499 }
500
501 fn update_reachability_from_macro(
504 &mut self,
505 local_def_id: LocalDefId,
506 md: &MacroDef,
507 macro_ev: EffectiveVisibility,
508 ) {
509 let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id);
511 let attrs = self.tcx.hir_attrs(hir_id);
512
513 if {
'done:
{
for i in attrs {
let i: &rustc_hir::Attribute = i;
match i {
rustc_hir::Attribute::Parsed(AttributeKind::RustcMacroTransparency(x))
=> {
break 'done Some(*x);
}
_ => {}
}
}
None
}
}find_attr!(attrs, AttributeKind::RustcMacroTransparency(x) => *x)
514 .unwrap_or(Transparency::fallback(md.macro_rules))
515 != Transparency::Opaque
516 {
517 return;
518 }
519
520 let macro_module_def_id = self.tcx.local_parent(local_def_id);
521 if self.tcx.def_kind(macro_module_def_id) != DefKind::Mod {
522 return;
524 }
525 let macro_module_def_id = LocalModDefId::new_unchecked(macro_module_def_id);
527
528 if self.effective_visibilities.public_at_level(local_def_id).is_none() {
529 return;
530 }
531
532 let mut module_def_id = macro_module_def_id;
535 loop {
536 let changed_reachability =
537 self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
538 if changed_reachability || module_def_id == LocalModDefId::CRATE_DEF_ID {
539 break;
540 }
541 module_def_id = LocalModDefId::new_unchecked(self.tcx.local_parent(module_def_id));
542 }
543 }
544
545 fn update_macro_reachable(
548 &mut self,
549 module_def_id: LocalModDefId,
550 defining_mod: LocalModDefId,
551 macro_ev: EffectiveVisibility,
552 ) -> bool {
553 if self.macro_reachable.insert((module_def_id, defining_mod)) {
554 for child in self.tcx.module_children_local(module_def_id.to_local_def_id()) {
555 if let Res::Def(def_kind, def_id) = child.res
556 && let Some(def_id) = def_id.as_local()
557 && child.vis.is_accessible_from(defining_mod, self.tcx)
558 {
559 let vis = self.tcx.local_visibility(def_id);
560 self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev);
561 }
562 }
563 true
564 } else {
565 false
566 }
567 }
568
569 fn update_macro_reachable_def(
570 &mut self,
571 def_id: LocalDefId,
572 def_kind: DefKind,
573 vis: ty::Visibility,
574 module: LocalModDefId,
575 macro_ev: EffectiveVisibility,
576 ) {
577 self.update(def_id, macro_ev, Level::Reachable);
578 match def_kind {
579 DefKind::Const | DefKind::Static { .. } | DefKind::TraitAlias | DefKind::TyAlias => {
581 if vis.is_accessible_from(module, self.tcx) {
582 self.update(def_id, macro_ev, Level::Reachable);
583 }
584 }
585
586 DefKind::Macro(_) => {
591 let item = self.tcx.hir_expect_item(def_id);
592 if let hir::ItemKind::Macro(_, MacroDef { macro_rules: false, .. }, _) = item.kind {
593 if vis.is_accessible_from(module, self.tcx) {
594 self.update(def_id, macro_ev, Level::Reachable);
595 }
596 }
597 }
598
599 DefKind::Mod => {
604 if vis.is_accessible_from(module, self.tcx) {
605 self.update_macro_reachable(
606 LocalModDefId::new_unchecked(def_id),
607 module,
608 macro_ev,
609 );
610 }
611 }
612
613 DefKind::Struct | DefKind::Union => {
614 let struct_def = self.tcx.adt_def(def_id);
616 for field in &struct_def.non_enum_variant().fields {
617 let def_id = field.did.expect_local();
618 let field_vis = self.tcx.local_visibility(def_id);
619 if field_vis.is_accessible_from(module, self.tcx) {
620 self.reach(def_id, macro_ev).ty();
621 }
622 }
623 }
624
625 DefKind::AssocConst
628 | DefKind::AssocTy
629 | DefKind::ConstParam
630 | DefKind::Ctor(_, _)
631 | DefKind::Enum
632 | DefKind::ForeignTy
633 | DefKind::Fn
634 | DefKind::OpaqueTy
635 | DefKind::AssocFn
636 | DefKind::Trait
637 | DefKind::TyParam
638 | DefKind::Variant
639 | DefKind::LifetimeParam
640 | DefKind::ExternCrate
641 | DefKind::Use
642 | DefKind::ForeignMod
643 | DefKind::AnonConst
644 | DefKind::InlineConst
645 | DefKind::Field
646 | DefKind::GlobalAsm
647 | DefKind::Impl { .. }
648 | DefKind::Closure
649 | DefKind::SyntheticCoroutineBody => (),
650 }
651 }
652}
653
654impl<'tcx> EmbargoVisitor<'tcx> {
655 fn check_assoc_item(&mut self, item: &ty::AssocItem, item_ev: EffectiveVisibility) {
656 let def_id = item.def_id.expect_local();
657 let tcx = self.tcx;
658 let mut reach = self.reach(def_id, item_ev);
659 reach.generics().predicates();
660 if assoc_has_type_of(tcx, item) {
661 reach.ty();
662 }
663 if item.is_type() && item.container == AssocContainer::Trait {
664 reach.bounds();
665 }
666 }
667
668 fn check_def_id(&mut self, owner_id: OwnerId) {
669 let item_ev = self.get(owner_id.def_id);
672 match self.tcx.def_kind(owner_id) {
673 DefKind::Use | DefKind::ExternCrate | DefKind::GlobalAsm => {}
675 DefKind::Mod => {}
677 DefKind::Macro { .. } => {
678 if let Some(item_ev) = item_ev {
679 let (_, macro_def, _) =
680 self.tcx.hir_expect_item(owner_id.def_id).expect_macro();
681 self.update_reachability_from_macro(owner_id.def_id, macro_def, item_ev);
682 }
683 }
684 DefKind::ForeignTy
685 | DefKind::Const
686 | DefKind::Static { .. }
687 | DefKind::Fn
688 | DefKind::TyAlias => {
689 if let Some(item_ev) = item_ev {
690 self.reach(owner_id.def_id, item_ev).generics().predicates().ty();
691 }
692 }
693 DefKind::Trait => {
694 if let Some(item_ev) = item_ev {
695 self.reach(owner_id.def_id, item_ev).generics().predicates();
696
697 for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
698 let def_id = assoc_item.def_id.expect_local();
699 self.update(def_id, item_ev, Level::Reachable);
700
701 self.check_assoc_item(assoc_item, item_ev);
702 }
703 }
704 }
705 DefKind::TraitAlias => {
706 if let Some(item_ev) = item_ev {
707 self.reach(owner_id.def_id, item_ev).generics().predicates();
708 }
709 }
710 DefKind::Impl { of_trait } => {
711 let item_ev = EffectiveVisibility::of_impl::<true>(
722 owner_id.def_id,
723 of_trait,
724 self.tcx,
725 &self.effective_visibilities,
726 );
727
728 self.update_eff_vis(owner_id.def_id, item_ev, None, Level::Direct);
729
730 {
731 let mut reach = self.reach(owner_id.def_id, item_ev);
732 reach.generics().predicates().ty();
733 if of_trait {
734 reach.trait_ref();
735 }
736 }
737
738 for assoc_item in self.tcx.associated_items(owner_id).in_definition_order() {
739 let def_id = assoc_item.def_id.expect_local();
740 let max_vis =
741 if of_trait { None } else { Some(self.tcx.local_visibility(def_id)) };
742 self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);
743
744 if let Some(impl_item_ev) = self.get(def_id) {
745 self.check_assoc_item(assoc_item, impl_item_ev);
746 }
747 }
748 }
749 DefKind::Enum => {
750 if let Some(item_ev) = item_ev {
751 self.reach(owner_id.def_id, item_ev).generics().predicates();
752 }
753 let def = self.tcx.adt_def(owner_id);
754 for variant in def.variants() {
755 if let Some(item_ev) = item_ev {
756 self.update(variant.def_id.expect_local(), item_ev, Level::Reachable);
757 }
758
759 if let Some(variant_ev) = self.get(variant.def_id.expect_local()) {
760 if let Some(ctor_def_id) = variant.ctor_def_id() {
761 self.update(ctor_def_id.expect_local(), variant_ev, Level::Reachable);
762 }
763
764 for field in &variant.fields {
765 let field = field.did.expect_local();
766 self.update(field, variant_ev, Level::Reachable);
767 self.reach(field, variant_ev).ty();
768 }
769 self.reach(owner_id.def_id, variant_ev).ty();
772 }
773 if let Some(ctor_def_id) = variant.ctor_def_id() {
774 if let Some(ctor_ev) = self.get(ctor_def_id.expect_local()) {
775 self.reach(owner_id.def_id, ctor_ev).ty();
776 }
777 }
778 }
779 }
780 DefKind::Struct | DefKind::Union => {
781 let def = self.tcx.adt_def(owner_id).non_enum_variant();
782 if let Some(item_ev) = item_ev {
783 self.reach(owner_id.def_id, item_ev).generics().predicates();
784 for field in &def.fields {
785 let field = field.did.expect_local();
786 self.update(field, item_ev, Level::Reachable);
787 if let Some(field_ev) = self.get(field) {
788 self.reach(field, field_ev).ty();
789 }
790 }
791 }
792 if let Some(ctor_def_id) = def.ctor_def_id() {
793 if let Some(item_ev) = item_ev {
794 self.update(ctor_def_id.expect_local(), item_ev, Level::Reachable);
795 }
796 if let Some(ctor_ev) = self.get(ctor_def_id.expect_local()) {
797 self.reach(owner_id.def_id, ctor_ev).ty();
798 }
799 }
800 }
801 DefKind::ForeignMod => {}
803 DefKind::Field
804 | DefKind::Variant
805 | DefKind::AssocFn
806 | DefKind::AssocTy
807 | DefKind::AssocConst
808 | DefKind::TyParam
809 | DefKind::AnonConst
810 | DefKind::InlineConst
811 | DefKind::OpaqueTy
812 | DefKind::Closure
813 | DefKind::SyntheticCoroutineBody
814 | DefKind::ConstParam
815 | DefKind::LifetimeParam
816 | DefKind::Ctor(..) => {
817 ::rustc_middle::util::bug::bug_fmt(format_args!("should be checked while checking parent"))bug!("should be checked while checking parent")
818 }
819 }
820 }
821}
822
823impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
824 fn generics(&mut self) -> &mut Self {
825 for param in &self.ev.tcx.generics_of(self.item_def_id).own_params {
826 if let GenericParamDefKind::Const { .. } = param.kind {
827 self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
828 }
829 if let Some(default) = param.default_value(self.ev.tcx) {
830 self.visit(default.instantiate_identity());
831 }
832 }
833 self
834 }
835
836 fn predicates(&mut self) -> &mut Self {
837 self.visit_predicates(self.ev.tcx.explicit_predicates_of(self.item_def_id));
838 self
839 }
840
841 fn bounds(&mut self) -> &mut Self {
842 self.visit_clauses(self.ev.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
843 self
844 }
845
846 fn ty(&mut self) -> &mut Self {
847 self.visit(self.ev.tcx.type_of(self.item_def_id).instantiate_identity());
848 self
849 }
850
851 fn trait_ref(&mut self) -> &mut Self {
852 self.visit_trait(self.ev.tcx.impl_trait_ref(self.item_def_id).instantiate_identity());
853 self
854 }
855}
856
857impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
858 fn tcx(&self) -> TyCtxt<'tcx> {
859 self.ev.tcx
860 }
861 fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
862 if let Some(def_id) = def_id.as_local() {
863 let max_vis = (self.level != Level::ReachableThroughImplTrait)
867 .then(|| self.ev.tcx.local_visibility(def_id));
868 self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level);
869 }
870 }
871}
872
873pub struct TestReachabilityVisitor<'a, 'tcx> {
875 tcx: TyCtxt<'tcx>,
876 effective_visibilities: &'a EffectiveVisibilities,
877}
878
879impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
880 fn effective_visibility_diagnostic(&self, def_id: LocalDefId) {
881 if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) {
882 let mut error_msg = String::new();
883 let span = self.tcx.def_span(def_id.to_def_id());
884 if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) {
885 for level in Level::all_levels() {
886 let vis_str = effective_vis.at_level(level).to_string(def_id, self.tcx);
887 if level != Level::Direct {
888 error_msg.push_str(", ");
889 }
890 error_msg.push_str(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?}: {1}", level, vis_str))
})format!("{level:?}: {vis_str}"));
891 }
892 } else {
893 error_msg.push_str("not in the table");
894 }
895 self.tcx.dcx().emit_err(ReportEffectiveVisibility { span, descr: error_msg });
896 }
897 }
898}
899
900impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
901 fn check_def_id(&self, owner_id: OwnerId) {
902 self.effective_visibility_diagnostic(owner_id.def_id);
903
904 match self.tcx.def_kind(owner_id) {
905 DefKind::Enum => {
906 let def = self.tcx.adt_def(owner_id.def_id);
907 for variant in def.variants() {
908 self.effective_visibility_diagnostic(variant.def_id.expect_local());
909 if let Some(ctor_def_id) = variant.ctor_def_id() {
910 self.effective_visibility_diagnostic(ctor_def_id.expect_local());
911 }
912 for field in &variant.fields {
913 self.effective_visibility_diagnostic(field.did.expect_local());
914 }
915 }
916 }
917 DefKind::Struct | DefKind::Union => {
918 let def = self.tcx.adt_def(owner_id.def_id).non_enum_variant();
919 if let Some(ctor_def_id) = def.ctor_def_id() {
920 self.effective_visibility_diagnostic(ctor_def_id.expect_local());
921 }
922 for field in &def.fields {
923 self.effective_visibility_diagnostic(field.did.expect_local());
924 }
925 }
926 _ => {}
927 }
928 }
929}
930
931struct NamePrivacyVisitor<'tcx> {
937 tcx: TyCtxt<'tcx>,
938 maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
939}
940
941impl<'tcx> NamePrivacyVisitor<'tcx> {
942 #[track_caller]
946 fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
947 self.maybe_typeck_results
948 .expect("`NamePrivacyVisitor::typeck_results` called outside of body")
949 }
950
951 fn check_field(
953 &self,
954 hir_id: hir::HirId, use_ctxt: Span, def: ty::AdtDef<'tcx>, field: &'tcx ty::FieldDef,
958 ) -> bool {
959 if def.is_enum() {
960 return true;
961 }
962
963 let ident = Ident::new(sym::dummy, use_ctxt);
965 let (_, def_id) = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id);
966 !field.vis.is_accessible_from(def_id, self.tcx)
967 }
968
969 fn emit_unreachable_field_error(
971 &self,
972 fields: Vec<(Symbol, Span, bool )>,
973 def: ty::AdtDef<'tcx>, update_syntax: Option<Span>,
975 struct_span: Span,
976 ) {
977 if def.is_enum() || fields.is_empty() {
978 return;
979 }
980
981 let Some(field_names) = listify(&fields[..], |(n, _, _)| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", n))
})format!("`{n}`")) else { return };
993 let span: MultiSpan = fields.iter().map(|(_, span, _)| *span).collect::<Vec<Span>>().into();
994
995 let rest_field_names: Vec<_> =
997 fields.iter().filter(|(_, _, is_present)| !is_present).map(|(n, _, _)| n).collect();
998 let rest_len = rest_field_names.len();
999 let rest_field_names =
1000 listify(&rest_field_names[..], |n| ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`{0}`", n))
})format!("`{n}`")).unwrap_or_default();
1001 let labels = fields
1003 .iter()
1004 .filter(|(_, _, is_present)| *is_present)
1005 .map(|(_, span, _)| FieldIsPrivateLabel::Other { span: *span })
1006 .chain(update_syntax.iter().map(|span| FieldIsPrivateLabel::IsUpdateSyntax {
1007 span: *span,
1008 rest_field_names: rest_field_names.clone(),
1009 rest_len,
1010 }))
1011 .collect();
1012
1013 self.tcx.dcx().emit_err(FieldIsPrivate {
1014 span,
1015 struct_span: if self
1016 .tcx
1017 .sess
1018 .source_map()
1019 .is_multiline(fields[0].1.between(struct_span))
1020 {
1021 Some(struct_span)
1022 } else {
1023 None
1024 },
1025 field_names,
1026 variant_descr: def.variant_descr(),
1027 def_path_str: self.tcx.def_path_str(def.did()),
1028 labels,
1029 len: fields.len(),
1030 });
1031 }
1032
1033 fn check_expanded_fields(
1034 &self,
1035 adt: ty::AdtDef<'tcx>,
1036 variant: &'tcx ty::VariantDef,
1037 fields: &[hir::ExprField<'tcx>],
1038 hir_id: hir::HirId,
1039 span: Span,
1040 struct_span: Span,
1041 ) {
1042 let mut failed_fields = ::alloc::vec::Vec::new()vec![];
1043 for (vf_index, variant_field) in variant.fields.iter_enumerated() {
1044 let field =
1045 fields.iter().find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
1046 let (hir_id, use_ctxt, span) = match field {
1047 Some(field) => (field.hir_id, field.ident.span, field.span),
1048 None => (hir_id, span, span),
1049 };
1050 if self.check_field(hir_id, use_ctxt, adt, variant_field) {
1051 let name = match field {
1052 Some(field) => field.ident.name,
1053 None => variant_field.name,
1054 };
1055 failed_fields.push((name, span, field.is_some()));
1056 }
1057 }
1058 self.emit_unreachable_field_error(failed_fields, adt, Some(span), struct_span);
1059 }
1060}
1061
1062impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
1063 fn visit_nested_body(&mut self, body_id: hir::BodyId) {
1064 let new_typeck_results = self.tcx.typeck_body(body_id);
1065 if new_typeck_results.tainted_by_errors.is_some() {
1067 return;
1068 }
1069 let old_maybe_typeck_results = self.maybe_typeck_results.replace(new_typeck_results);
1070 self.visit_body(self.tcx.hir_body(body_id));
1071 self.maybe_typeck_results = old_maybe_typeck_results;
1072 }
1073
1074 fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
1075 if let hir::ExprKind::Struct(qpath, fields, ref base) = expr.kind {
1076 let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
1077 let adt = self.typeck_results().expr_ty(expr).ty_adt_def().unwrap();
1078 let variant = adt.variant_of_res(res);
1079 match *base {
1080 hir::StructTailExpr::Base(base) => {
1081 self.check_expanded_fields(
1085 adt,
1086 variant,
1087 fields,
1088 base.hir_id,
1089 base.span,
1090 qpath.span(),
1091 );
1092 }
1093 hir::StructTailExpr::DefaultFields(span) => {
1094 self.check_expanded_fields(
1095 adt,
1096 variant,
1097 fields,
1098 expr.hir_id,
1099 span,
1100 qpath.span(),
1101 );
1102 }
1103 hir::StructTailExpr::None => {
1104 let mut failed_fields = ::alloc::vec::Vec::new()vec![];
1105 for field in fields {
1106 let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
1107 let index = self.typeck_results().field_index(field.hir_id);
1108 if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
1109 failed_fields.push((field.ident.name, field.ident.span, true));
1110 }
1111 }
1112 self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
1113 }
1114 }
1115 }
1116
1117 intravisit::walk_expr(self, expr);
1118 }
1119
1120 fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
1121 if let PatKind::Struct(ref qpath, fields, _) = pat.kind {
1122 let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
1123 let adt = self.typeck_results().pat_ty(pat).ty_adt_def().unwrap();
1124 let variant = adt.variant_of_res(res);
1125 let mut failed_fields = ::alloc::vec::Vec::new()vec![];
1126 for field in fields {
1127 let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
1128 let index = self.typeck_results().field_index(field.hir_id);
1129 if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
1130 failed_fields.push((field.ident.name, field.ident.span, true));
1131 }
1132 }
1133 self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
1134 }
1135
1136 intravisit::walk_pat(self, pat);
1137 }
1138}
1139
1140struct TypePrivacyVisitor<'tcx> {
1145 tcx: TyCtxt<'tcx>,
1146 module_def_id: LocalModDefId,
1147 maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
1148 span: Span,
1149}
1150
1151impl<'tcx> TypePrivacyVisitor<'tcx> {
1152 fn item_is_accessible(&self, did: DefId) -> bool {
1153 self.tcx.visibility(did).is_accessible_from(self.module_def_id, self.tcx)
1154 }
1155
1156 fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
1158 self.span = span;
1159 let typeck_results = self
1160 .maybe_typeck_results
1161 .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"));
1162 let result: ControlFlow<()> = try {
1163 self.visit(typeck_results.node_type(id))?;
1164 self.visit(typeck_results.node_args(id))?;
1165 if let Some(adjustments) = typeck_results.adjustments().get(id) {
1166 adjustments.iter().try_for_each(|adjustment| self.visit(adjustment.target))?;
1167 }
1168 };
1169 result.is_break()
1170 }
1171
1172 fn check_def_id(&self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1173 let is_error = !self.item_is_accessible(def_id);
1174 if is_error {
1175 self.tcx.dcx().emit_err(ItemIsPrivate { span: self.span, kind, descr: descr.into() });
1176 }
1177 is_error
1178 }
1179}
1180
1181impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
1182 type Result = ControlFlow<()>;
1183 fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
1184 self.span = span;
1185 value.visit_with(&mut self.skeleton())
1186 }
1187}
1188
1189impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
1190 fn visit_nested_body(&mut self, body_id: hir::BodyId) {
1191 let old_maybe_typeck_results =
1192 self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
1193 self.visit_body(self.tcx.hir_body(body_id));
1194 self.maybe_typeck_results = old_maybe_typeck_results;
1195 }
1196
1197 fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
1198 self.span = hir_ty.span;
1199 if self
1200 .visit(
1201 self.maybe_typeck_results
1202 .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"))
1203 .node_type(hir_ty.hir_id),
1204 )
1205 .is_break()
1206 {
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.visit(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.visit(self.tcx.type_of(def_id).instantiate_identity()).is_break() {
1256 return;
1257 }
1258 } else {
1259 self.tcx
1260 .dcx()
1261 .span_delayed_bug(expr.span, "no type-dependent def for method call");
1262 }
1263 }
1264 _ => {}
1265 }
1266
1267 intravisit::walk_expr(self, expr);
1268 }
1269
1270 fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: Span) {
1277 let def = match qpath {
1278 hir::QPath::Resolved(_, path) => match path.res {
1279 Res::Def(kind, def_id) => Some((kind, def_id)),
1280 _ => None,
1281 },
1282 hir::QPath::TypeRelative(..) => {
1283 match self.maybe_typeck_results {
1284 Some(typeck_results) => typeck_results.type_dependent_def(id),
1285 None => None,
1287 }
1288 }
1289 };
1290 let def = def.filter(|(kind, _)| {
1291 #[allow(non_exhaustive_omitted_patterns)] match kind {
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy |
DefKind::Static { .. } => true,
_ => false,
}matches!(
1292 kind,
1293 DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static { .. }
1294 )
1295 });
1296 if let Some((kind, def_id)) = def {
1297 let is_local_static =
1298 if let DefKind::Static { .. } = kind { def_id.is_local() } else { false };
1299 if !self.item_is_accessible(def_id) && !is_local_static {
1300 let name = match *qpath {
1301 hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
1302 hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
1303 };
1304 let kind = self.tcx.def_descr(def_id);
1305 let sess = self.tcx.sess;
1306 let _ = match name {
1307 Some(name) => {
1308 sess.dcx().emit_err(ItemIsPrivate { span, kind, descr: (&name).into() })
1309 }
1310 None => sess.dcx().emit_err(UnnamedItemIsPrivate { span, kind }),
1311 };
1312 return;
1313 }
1314 }
1315
1316 intravisit::walk_qpath(self, qpath, id);
1317 }
1318
1319 fn visit_pat(&mut self, pattern: &'tcx hir::Pat<'tcx>) {
1321 if self.check_expr_pat_type(pattern.hir_id, pattern.span) {
1322 return;
1324 }
1325
1326 intravisit::walk_pat(self, pattern);
1327 }
1328
1329 fn visit_local(&mut self, local: &'tcx hir::LetStmt<'tcx>) {
1330 if let Some(init) = local.init {
1331 if self.check_expr_pat_type(init.hir_id, init.span) {
1332 return;
1334 }
1335 }
1336
1337 intravisit::walk_local(self, local);
1338 }
1339}
1340
1341impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
1342 type Result = ControlFlow<()>;
1343 fn tcx(&self) -> TyCtxt<'tcx> {
1344 self.tcx
1345 }
1346 fn visit_def_id(
1347 &mut self,
1348 def_id: DefId,
1349 kind: &str,
1350 descr: &dyn fmt::Display,
1351 ) -> Self::Result {
1352 if self.check_def_id(def_id, kind, descr) {
1353 ControlFlow::Break(())
1354 } else {
1355 ControlFlow::Continue(())
1356 }
1357 }
1358}
1359
1360struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
1366 tcx: TyCtxt<'tcx>,
1367 item_def_id: LocalDefId,
1368 required_visibility: ty::Visibility,
1370 required_effective_vis: Option<EffectiveVisibility>,
1371 hard_error: bool = false,
1372 in_primary_interface: bool = true,
1373 skip_assoc_tys: bool = false,
1374}
1375
1376impl SearchInterfaceForPrivateItemsVisitor<'_> {
1377 fn generics(&mut self) -> &mut Self {
1378 self.in_primary_interface = true;
1379 for param in &self.tcx.generics_of(self.item_def_id).own_params {
1380 if let GenericParamDefKind::Const { .. } = param.kind {
1381 let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
1382 }
1383 if let Some(default) = param.default_value(self.tcx) {
1384 let _ = self.visit(default.instantiate_identity());
1385 }
1386 }
1387 self
1388 }
1389
1390 fn predicates(&mut self) -> &mut Self {
1391 self.in_primary_interface = false;
1392 let _ = self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id));
1399 self
1400 }
1401
1402 fn bounds(&mut self) -> &mut Self {
1403 self.in_primary_interface = false;
1404 let _ = self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
1405 self
1406 }
1407
1408 fn ty(&mut self) -> &mut Self {
1409 self.in_primary_interface = true;
1410 let _ = self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity());
1411 self
1412 }
1413
1414 fn trait_ref(&mut self) -> &mut Self {
1415 self.in_primary_interface = true;
1416 let _ = self.visit_trait(self.tcx.impl_trait_ref(self.item_def_id).instantiate_identity());
1417 self
1418 }
1419
1420 fn check_def_id(&self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
1421 if self.leaks_private_dep(def_id) {
1422 self.tcx.emit_node_span_lint(
1423 lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
1424 self.tcx.local_def_id_to_hir_id(self.item_def_id),
1425 self.tcx.def_span(self.item_def_id.to_def_id()),
1426 FromPrivateDependencyInPublicInterface {
1427 kind,
1428 descr: descr.into(),
1429 krate: self.tcx.crate_name(def_id.krate),
1430 },
1431 );
1432 }
1433
1434 let Some(local_def_id) = def_id.as_local() else {
1435 return false;
1436 };
1437
1438 let vis = self.tcx.local_visibility(local_def_id);
1439 if self.hard_error && !vis.is_at_least(self.required_visibility, self.tcx) {
1440 let vis_descr = match vis {
1441 ty::Visibility::Public => "public",
1442 ty::Visibility::Restricted(vis_def_id) => {
1443 if vis_def_id
1444 == self.tcx.parent_module_from_def_id(local_def_id).to_local_def_id()
1445 {
1446 "private"
1447 } else if vis_def_id.is_top_level_module() {
1448 "crate-private"
1449 } else {
1450 "restricted"
1451 }
1452 }
1453 };
1454
1455 let span = self.tcx.def_span(self.item_def_id.to_def_id());
1456 let vis_span = self.tcx.def_span(def_id);
1457 self.tcx.dcx().emit_err(InPublicInterface {
1458 span,
1459 vis_descr,
1460 kind,
1461 descr: descr.into(),
1462 vis_span,
1463 });
1464 return false;
1465 }
1466
1467 let Some(effective_vis) = self.required_effective_vis else {
1468 return false;
1469 };
1470
1471 let reachable_at_vis = *effective_vis.at_level(Level::Reachable);
1472
1473 if !vis.is_at_least(reachable_at_vis, self.tcx) {
1474 let lint = if self.in_primary_interface {
1475 lint::builtin::PRIVATE_INTERFACES
1476 } else {
1477 lint::builtin::PRIVATE_BOUNDS
1478 };
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 compiler/rustc_privacy/src/lib.rs:1512",
"rustc_privacy", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("leaks_private_dep(item_id={0:?})={1}",
item_id, ret) as &dyn Value))])
});
} else { ; }
};debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
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 lint::builtin::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 && !item.is_impl_trait_in_trait();
1596 check.generics().predicates();
1597 if assoc_has_type_of(self.tcx, item) {
1598 check.hard_error = check.hard_error && item.defaultness(self.tcx).has_value();
1599 check.ty();
1600 }
1601 if is_assoc_ty && item.container == AssocContainer::Trait {
1602 check.hard_error = false;
1603 check.bounds();
1604 }
1605 }
1606
1607 fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
1608 self.effective_visibilities.effective_vis(def_id).copied()
1609 }
1610
1611 fn check_item(&self, id: ItemId) {
1612 let tcx = self.tcx;
1613 let def_id = id.owner_id.def_id;
1614 let item_visibility = tcx.local_visibility(def_id);
1615 let effective_vis = self.get(def_id);
1616 let def_kind = tcx.def_kind(def_id);
1617
1618 match def_kind {
1619 DefKind::Const | DefKind::Static { .. } | DefKind::Fn | DefKind::TyAlias => {
1620 if let DefKind::TyAlias = def_kind {
1621 self.check_unnameable(def_id, effective_vis);
1622 }
1623 self.check(def_id, item_visibility, effective_vis).generics().predicates().ty();
1624 }
1625 DefKind::OpaqueTy => {
1626 self.check(def_id, item_visibility, effective_vis).generics().bounds();
1629 }
1630 DefKind::Trait => {
1631 self.check_unnameable(def_id, effective_vis);
1632
1633 self.check(def_id, item_visibility, effective_vis).generics().predicates();
1634
1635 for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
1636 self.check_assoc_item(assoc_item, item_visibility, effective_vis);
1637 }
1638 }
1639 DefKind::TraitAlias => {
1640 self.check(def_id, item_visibility, effective_vis).generics().predicates();
1641 }
1642 DefKind::Enum => {
1643 self.check_unnameable(def_id, effective_vis);
1644 self.check(def_id, item_visibility, effective_vis).generics().predicates();
1645
1646 let adt = tcx.adt_def(id.owner_id);
1647 for field in adt.all_fields() {
1648 self.check(field.did.expect_local(), item_visibility, effective_vis).ty();
1649 }
1650 }
1651 DefKind::Struct | DefKind::Union => {
1653 self.check_unnameable(def_id, effective_vis);
1654 self.check(def_id, item_visibility, effective_vis).generics().predicates();
1655
1656 let adt = tcx.adt_def(id.owner_id);
1657 for field in adt.all_fields() {
1658 let visibility = min(item_visibility, field.vis.expect_local(), tcx);
1659 let field_ev = self.get(field.did.expect_local());
1660
1661 self.check(field.did.expect_local(), visibility, field_ev).ty();
1662 }
1663 }
1664 DefKind::ForeignMod => {}
1666 DefKind::Impl { of_trait } => {
1671 let impl_vis =
1672 ty::Visibility::of_impl::<false>(def_id, of_trait, tcx, &Default::default());
1673
1674 let impl_ev = EffectiveVisibility::of_impl::<false>(
1686 def_id,
1687 of_trait,
1688 tcx,
1689 self.effective_visibilities,
1690 );
1691
1692 let mut check = self.check(def_id, impl_vis, Some(impl_ev));
1693
1694 if !of_trait {
1697 check.generics().predicates();
1698 }
1699
1700 check.skip_assoc_tys = true;
1704 check.ty();
1705 if of_trait {
1706 check.trait_ref();
1707 }
1708
1709 for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
1710 let impl_item_vis = if !of_trait {
1711 min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx)
1712 } else {
1713 impl_vis
1714 };
1715
1716 let impl_item_ev = if !of_trait {
1717 self.get(assoc_item.def_id.expect_local())
1718 .map(|ev| ev.min(impl_ev, self.tcx))
1719 } else {
1720 Some(impl_ev)
1721 };
1722
1723 self.check_assoc_item(assoc_item, impl_item_vis, impl_item_ev);
1724 }
1725 }
1726 _ => {}
1727 }
1728 }
1729
1730 fn check_foreign_item(&self, id: ForeignItemId) {
1731 let tcx = self.tcx;
1732 let def_id = id.owner_id.def_id;
1733 let item_visibility = tcx.local_visibility(def_id);
1734 let effective_vis = self.get(def_id);
1735
1736 if let DefKind::ForeignTy = self.tcx.def_kind(def_id) {
1737 self.check_unnameable(def_id, effective_vis);
1738 }
1739
1740 self.check(def_id, item_visibility, effective_vis).generics().predicates().ty();
1741 }
1742}
1743
1744pub fn provide(providers: &mut Providers) {
1745 *providers = Providers {
1746 effective_visibilities,
1747 check_private_in_public,
1748 check_mod_privacy,
1749 ..*providers
1750 };
1751}
1752
1753fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
1754 let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None };
1756 tcx.hir_visit_item_likes_in_module(module_def_id, &mut visitor);
1757
1758 let span = tcx.def_span(module_def_id);
1761 let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span };
1762
1763 let module = tcx.hir_module_items(module_def_id);
1764 for def_id in module.definitions() {
1765 let _ = rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor);
1766
1767 if let Some(body_id) = tcx.hir_maybe_body_owned_by(def_id) {
1768 visitor.visit_nested_body(body_id.id());
1769 }
1770
1771 if let DefKind::Impl { of_trait: true } = tcx.def_kind(def_id) {
1772 let trait_ref = tcx.impl_trait_ref(def_id);
1773 let trait_ref = trait_ref.instantiate_identity();
1774 visitor.span =
1775 tcx.hir_expect_item(def_id).expect_impl().of_trait.unwrap().trait_ref.path.span;
1776 let _ =
1777 visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref.print_only_trait_path());
1778 }
1779 }
1780}
1781
1782fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
1783 let mut visitor = EmbargoVisitor {
1786 tcx,
1787 effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
1788 macro_reachable: Default::default(),
1789 changed: false,
1790 };
1791
1792 visitor.effective_visibilities.check_invariants(tcx);
1793
1794 let impl_trait_pass = !tcx.sess.opts.actually_rustdoc;
1798 if impl_trait_pass {
1799 let krate = tcx.hir_crate_items(());
1802 for id in krate.opaques() {
1803 let opaque = tcx.hir_node_by_def_id(id).expect_opaque_ty();
1804 let should_visit = match opaque.origin {
1805 hir::OpaqueTyOrigin::FnReturn {
1806 parent,
1807 in_trait_or_impl: Some(hir::RpitContext::Trait),
1808 }
1809 | hir::OpaqueTyOrigin::AsyncFn {
1810 parent,
1811 in_trait_or_impl: Some(hir::RpitContext::Trait),
1812 } => match tcx.hir_node_by_def_id(parent).expect_trait_item().expect_fn().1 {
1813 hir::TraitFn::Required(_) => false,
1814 hir::TraitFn::Provided(..) => true,
1815 },
1816
1817 hir::OpaqueTyOrigin::FnReturn {
1820 in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
1821 ..
1822 }
1823 | hir::OpaqueTyOrigin::AsyncFn {
1824 in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
1825 ..
1826 }
1827 | hir::OpaqueTyOrigin::TyAlias { .. } => true,
1828 };
1829 if should_visit {
1830 let pub_ev = EffectiveVisibility::from_vis(ty::Visibility::Public);
1834 visitor
1835 .reach_through_impl_trait(opaque.def_id, pub_ev)
1836 .generics()
1837 .predicates()
1838 .ty();
1839 }
1840 }
1841
1842 visitor.changed = false;
1843 }
1844
1845 let crate_items = tcx.hir_crate_items(());
1846 loop {
1847 for id in crate_items.free_items() {
1848 visitor.check_def_id(id.owner_id);
1849 }
1850 for id in crate_items.foreign_items() {
1851 visitor.check_def_id(id.owner_id);
1852 }
1853 if visitor.changed {
1854 visitor.changed = false;
1855 } else {
1856 break;
1857 }
1858 }
1859 visitor.effective_visibilities.check_invariants(tcx);
1860
1861 let check_visitor =
1862 TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
1863 for id in crate_items.owners() {
1864 check_visitor.check_def_id(id);
1865 }
1866
1867 tcx.arena.alloc(visitor.effective_visibilities)
1868}
1869
1870fn check_private_in_public(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
1871 let effective_visibilities = tcx.effective_visibilities(());
1872 let checker = PrivateItemsInPublicInterfacesChecker { tcx, effective_visibilities };
1874
1875 let crate_items = tcx.hir_module_items(module_def_id);
1876 let _ = crate_items.par_items(|id| Ok(checker.check_item(id)));
1877 let _ = crate_items.par_foreign_items(|id| Ok(checker.check_foreign_item(id)));
1878}