Use `tidy` to sort crate attributes for all compiler crates.
We already do this for a number of crates, e.g. `rustc_middle`,
`rustc_span`, `rustc_metadata`, `rustc_span`, `rustc_errors`.
For the ones we don't, in many cases the attributes are a mess.
- There is no consistency about order of attribute kinds (e.g.
`allow`/`deny`/`feature`).
- Within attribute kind groups (e.g. the `feature` attributes),
sometimes the order is alphabetical, and sometimes there is no
particular order.
- Sometimes the attributes of a particular kind aren't even grouped
all together, e.g. there might be a `feature`, then an `allow`, then
another `feature`.
This commit extends the existing sorting to all compiler crates,
increasing consistency. If any new attribute line is added there is now
only one place it can go -- no need for arbitrary decisions.
Exceptions:
- `rustc_log`, `rustc_next_trait_solver` and `rustc_type_ir_macros`,
because they have no crate attributes.
- `rustc_codegen_gcc`, because it's quasi-external to rustc (e.g. it's
ignored in `rustfmt.toml`).
2024-06-12 13:49:36 +10:00
|
|
|
// tidy-alphabetical-start
|
|
|
|
|
#![allow(internal_features)]
|
2025-03-06 10:03:56 +11:00
|
|
|
#![cfg_attr(doc, recursion_limit = "256")] // FIXME(nnethercote): will be removed by #124141
|
2020-09-23 21:51:56 +02:00
|
|
|
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
2023-11-13 07:39:17 -05:00
|
|
|
#![doc(rust_logo)]
|
2022-06-22 14:17:14 +01:00
|
|
|
#![feature(associated_type_defaults)]
|
2022-07-27 07:27:52 +00:00
|
|
|
#![feature(let_chains)]
|
Use `tidy` to sort crate attributes for all compiler crates.
We already do this for a number of crates, e.g. `rustc_middle`,
`rustc_span`, `rustc_metadata`, `rustc_span`, `rustc_errors`.
For the ones we don't, in many cases the attributes are a mess.
- There is no consistency about order of attribute kinds (e.g.
`allow`/`deny`/`feature`).
- Within attribute kind groups (e.g. the `feature` attributes),
sometimes the order is alphabetical, and sometimes there is no
particular order.
- Sometimes the attributes of a particular kind aren't even grouped
all together, e.g. there might be a `feature`, then an `allow`, then
another `feature`.
This commit extends the existing sorting to all compiler crates,
increasing consistency. If any new attribute line is added there is now
only one place it can go -- no need for arbitrary decisions.
Exceptions:
- `rustc_log`, `rustc_next_trait_solver` and `rustc_type_ir_macros`,
because they have no crate attributes.
- `rustc_codegen_gcc`, because it's quasi-external to rustc (e.g. it's
ignored in `rustfmt.toml`).
2024-06-12 13:49:36 +10:00
|
|
|
#![feature(rustdoc_internals)]
|
|
|
|
|
#![feature(try_blocks)]
|
|
|
|
|
// tidy-alphabetical-end
|
2017-05-08 14:36:44 -07:00
|
|
|
|
2022-06-22 14:17:34 +01:00
|
|
|
mod errors;
|
|
|
|
|
|
2024-01-25 13:25:29 +03:00
|
|
|
use std::fmt;
|
2018-12-16 16:18:45 +03:00
|
|
|
use std::marker::PhantomData;
|
2020-10-21 14:26:34 +02:00
|
|
|
use std::ops::ControlFlow;
|
2024-07-29 08:13:50 +10:00
|
|
|
|
2022-06-22 14:11:39 +01:00
|
|
|
use errors::{
|
2022-08-05 16:43:52 +00:00
|
|
|
FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
|
2023-06-19 17:06:00 +03:00
|
|
|
ItemIsPrivate, PrivateInterfacesOrBoundsLint, ReportEffectiveVisibility, UnnameableTypesLint,
|
|
|
|
|
UnnamedItemIsPrivate,
|
2024-07-29 08:13:50 +10:00
|
|
|
};
|
2021-07-30 23:50:57 -07:00
|
|
|
use rustc_ast::MacroDef;
|
2024-02-24 17:22:28 -05:00
|
|
|
use rustc_ast::visit::{VisitorResult, try_visit};
|
2025-02-09 22:49:33 +01:00
|
|
|
use rustc_attr_parsing::AttributeKind;
|
2018-11-27 02:59:49 +00:00
|
|
|
use rustc_data_structures::fx::FxHashSet;
|
2022-03-05 07:28:41 +11:00
|
|
|
use rustc_data_structures::intern::Interned;
|
2025-01-31 20:36:44 +00:00
|
|
|
use rustc_errors::{MultiSpan, listify};
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::def::{DefKind, Res};
|
2023-04-26 20:53:51 +02:00
|
|
|
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId, LocalModDefId};
|
2025-01-11 19:12:36 +00:00
|
|
|
use rustc_hir::intravisit::{self, InferKind, Visitor};
|
|
|
|
|
use rustc_hir::{AmbigArg, AssocItemKind, ForeignItemKind, ItemId, ItemKind, PatKind};
|
2023-05-10 15:35:00 +03:00
|
|
|
use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level};
|
2023-05-15 06:24:45 +02:00
|
|
|
use rustc_middle::query::Providers;
|
2024-05-10 14:59:56 -04:00
|
|
|
use rustc_middle::ty::print::PrintTraitRefExt as _;
|
2023-02-22 19:51:17 +04:00
|
|
|
use rustc_middle::ty::{
|
2024-09-30 01:00:38 -04:00
|
|
|
self, Const, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
|
|
|
|
|
TypeVisitor,
|
2023-02-22 02:18:40 +00:00
|
|
|
};
|
2024-01-24 00:07:00 +03:00
|
|
|
use rustc_middle::{bug, span_bug};
|
2020-03-11 12:49:08 +01:00
|
|
|
use rustc_session::lint;
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::hygiene::Transparency;
|
2025-03-11 14:14:08 +11:00
|
|
|
use rustc_span::{Ident, Span, Symbol, sym};
|
2024-04-29 16:24:06 +10:00
|
|
|
use tracing::debug;
|
2024-12-13 14:47:11 +01:00
|
|
|
use {rustc_attr_parsing as attr, rustc_hir as hir};
|
2022-06-22 14:17:34 +01:00
|
|
|
|
2023-11-22 09:53:07 +11:00
|
|
|
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
2022-10-13 10:13:02 +01:00
|
|
|
|
2018-12-16 16:18:45 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// Generic infrastructure used to implement specific visitors below.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-05-18 14:57:45 +03:00
|
|
|
struct LazyDefPathStr<'tcx> {
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
write!(f, "{}", self.tcx.def_path_str(self.def_id))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-16 16:18:45 +03:00
|
|
|
/// Implemented to visit all `DefId`s in a type.
|
|
|
|
|
/// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them.
|
2018-12-31 03:02:40 +03:00
|
|
|
/// The idea is to visit "all components of a type", as documented in
|
2020-11-05 14:33:23 +01:00
|
|
|
/// <https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md#how-to-determine-visibility-of-a-type>.
|
2019-02-08 14:53:55 +01:00
|
|
|
/// The default type visitor (`TypeVisitor`) does most of the job, but it has some shortcomings.
|
|
|
|
|
/// First, it doesn't have overridable `fn visit_trait_ref`, so we have to catch trait `DefId`s
|
2018-12-31 03:02:40 +03:00
|
|
|
/// manually. Second, it doesn't visit some type components like signatures of fn types, or traits
|
2019-01-13 00:41:11 +03:00
|
|
|
/// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
|
2024-03-12 07:00:01 +00:00
|
|
|
pub trait DefIdVisitor<'tcx> {
|
2024-02-24 17:22:28 -05:00
|
|
|
type Result: VisitorResult = ();
|
2023-06-15 17:15:24 +03:00
|
|
|
const SHALLOW: bool = false;
|
|
|
|
|
const SKIP_ASSOC_TYS: bool = false;
|
2020-11-05 17:30:39 +01:00
|
|
|
|
2019-06-14 00:48:52 +03:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx>;
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display)
|
|
|
|
|
-> Self::Result;
|
2018-12-16 16:18:45 +03:00
|
|
|
|
|
|
|
|
/// Not overridden, but used to actually visit types and traits.
|
2019-06-11 22:03:44 +03:00
|
|
|
fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'tcx, Self> {
|
2018-12-16 16:18:45 +03:00
|
|
|
DefIdVisitorSkeleton {
|
|
|
|
|
def_id_visitor: self,
|
|
|
|
|
visited_opaque_tys: Default::default(),
|
|
|
|
|
dummy: Default::default(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit(&mut self, ty_fragment: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
|
2018-12-16 16:18:45 +03:00
|
|
|
ty_fragment.visit_with(&mut self.skeleton())
|
|
|
|
|
}
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> Self::Result {
|
2018-12-16 16:18:45 +03:00
|
|
|
self.skeleton().visit_trait(trait_ref)
|
|
|
|
|
}
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_predicates(&mut self, predicates: ty::GenericPredicates<'tcx>) -> Self::Result {
|
2023-06-22 18:17:13 +00:00
|
|
|
self.skeleton().visit_clauses(predicates.predicates)
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> Self::Result {
|
2023-06-22 18:17:13 +00:00
|
|
|
self.skeleton().visit_clauses(clauses)
|
2023-06-19 20:46:46 +00:00
|
|
|
}
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
|
2024-03-12 07:00:01 +00:00
|
|
|
pub struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> {
|
2018-12-16 16:18:45 +03:00
|
|
|
def_id_visitor: &'v mut V,
|
|
|
|
|
visited_opaque_tys: FxHashSet<DefId>,
|
2019-06-14 00:48:52 +03:00
|
|
|
dummy: PhantomData<TyCtxt<'tcx>>,
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
|
2019-06-11 22:03:44 +03:00
|
|
|
impl<'tcx, V> DefIdVisitorSkeleton<'_, 'tcx, V>
|
2019-06-12 00:11:55 +03:00
|
|
|
where
|
|
|
|
|
V: DefIdVisitor<'tcx> + ?Sized,
|
2018-12-16 16:18:45 +03:00
|
|
|
{
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> V::Result {
|
2023-07-11 22:35:29 +01:00
|
|
|
let TraitRef { def_id, args, .. } = trait_ref;
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(self.def_id_visitor.visit_def_id(
|
|
|
|
|
def_id,
|
|
|
|
|
"trait",
|
|
|
|
|
&trait_ref.print_only_trait_path()
|
|
|
|
|
));
|
|
|
|
|
if V::SHALLOW { V::Result::output() } else { args.visit_with(self) }
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
|
2024-05-13 10:00:38 -04:00
|
|
|
fn visit_projection_term(&mut self, projection: ty::AliasTerm<'tcx>) -> V::Result {
|
2022-10-05 04:16:05 +00:00
|
|
|
let tcx = self.def_id_visitor.tcx();
|
2023-07-11 22:35:29 +01:00
|
|
|
let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx);
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(self.visit_trait(trait_ref));
|
2023-06-15 17:15:24 +03:00
|
|
|
if V::SHALLOW {
|
2024-02-24 17:22:28 -05:00
|
|
|
V::Result::output()
|
2021-02-12 22:41:00 +00:00
|
|
|
} else {
|
2024-02-24 17:22:28 -05:00
|
|
|
V::Result::from_branch(
|
|
|
|
|
assoc_args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
|
|
|
|
|
)
|
2021-02-12 22:41:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_clause(&mut self, clause: ty::Clause<'tcx>) -> V::Result {
|
2023-06-19 20:46:46 +00:00
|
|
|
match clause.kind().skip_binder() {
|
2023-07-29 08:20:25 +00:00
|
|
|
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity: _ }) => {
|
2023-06-19 20:46:46 +00:00
|
|
|
self.visit_trait(trait_ref)
|
|
|
|
|
}
|
2024-10-20 19:49:11 +00:00
|
|
|
ty::ClauseKind::HostEffect(pred) => {
|
|
|
|
|
try_visit!(self.visit_trait(pred.trait_ref));
|
2024-10-29 23:42:59 +00:00
|
|
|
pred.constness.visit_with(self)
|
2024-10-20 19:49:11 +00:00
|
|
|
}
|
2024-05-13 10:00:38 -04:00
|
|
|
ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
|
|
|
|
projection_term: projection_ty,
|
|
|
|
|
term,
|
|
|
|
|
}) => {
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(term.visit_with(self));
|
2024-05-13 10:00:38 -04:00
|
|
|
self.visit_projection_term(projection_ty)
|
2020-06-21 12:26:17 +02:00
|
|
|
}
|
2023-06-19 20:46:46 +00:00
|
|
|
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _region)) => ty.visit_with(self),
|
2024-02-24 17:22:28 -05:00
|
|
|
ty::ClauseKind::RegionOutlives(..) => V::Result::output(),
|
2023-06-19 20:46:46 +00:00
|
|
|
ty::ClauseKind::ConstArgHasType(ct, ty) => {
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(ct.visit_with(self));
|
2023-02-17 09:32:33 +00:00
|
|
|
ty.visit_with(self)
|
|
|
|
|
}
|
2023-06-19 20:46:46 +00:00
|
|
|
ty::ClauseKind::ConstEvaluatable(ct) => ct.visit_with(self),
|
|
|
|
|
ty::ClauseKind::WellFormed(arg) => arg.visit_with(self),
|
2020-06-21 12:26:17 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> V::Result {
|
|
|
|
|
for &(clause, _) in clauses {
|
|
|
|
|
try_visit!(self.visit_clause(clause));
|
|
|
|
|
}
|
|
|
|
|
V::Result::output()
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-09 19:38:07 +00:00
|
|
|
impl<'tcx, V> TypeVisitor<TyCtxt<'tcx>> for DefIdVisitorSkeleton<'_, 'tcx, V>
|
2019-06-12 00:11:55 +03:00
|
|
|
where
|
|
|
|
|
V: DefIdVisitor<'tcx> + ?Sized,
|
2018-12-16 16:18:45 +03:00
|
|
|
{
|
2024-02-24 17:22:28 -05:00
|
|
|
type Result = V::Result;
|
2020-11-05 17:30:39 +01:00
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> Self::Result {
|
2023-07-18 07:22:46 +00:00
|
|
|
self.visit_clause(p.as_clause().unwrap())
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
|
2018-12-16 16:18:45 +03:00
|
|
|
let tcx = self.def_id_visitor.tcx();
|
2023-07-11 22:35:29 +01:00
|
|
|
// GenericArgs are not visited here because they are visited below
|
Folding revamp.
This commit makes type folding more like the way chalk does it.
Currently, `TypeFoldable` has `fold_with` and `super_fold_with` methods.
- `fold_with` is the standard entry point, and defaults to calling
`super_fold_with`.
- `super_fold_with` does the actual work of traversing a type.
- For a few types of interest (`Ty`, `Region`, etc.) `fold_with` instead
calls into a `TypeFolder`, which can then call back into
`super_fold_with`.
With the new approach, `TypeFoldable` has `fold_with` and
`TypeSuperFoldable` has `super_fold_with`.
- `fold_with` is still the standard entry point, *and* it does the
actual work of traversing a type, for all types except types of
interest.
- `super_fold_with` is only implemented for the types of interest.
Benefits of the new model.
- I find it easier to understand. The distinction between types of
interest and other types is clearer, and `super_fold_with` doesn't
exist for most types.
- With the current model is easy to get confused and implement a
`super_fold_with` method that should be left defaulted. (Some of the
precursor commits fixed such cases.)
- With the current model it's easy to call `super_fold_with` within
`TypeFolder` impls where `fold_with` should be called. The new
approach makes this mistake impossible, and this commit fixes a number
of such cases.
- It's potentially faster, because it avoids the `fold_with` ->
`super_fold_with` call in all cases except types of interest. A lot of
the time the compile would inline those away, but not necessarily
always.
2022-06-02 11:38:15 +10:00
|
|
|
// in `super_visit_with`.
|
2020-08-03 00:49:11 +02:00
|
|
|
match *ty.kind() {
|
2022-03-05 07:28:41 +11:00
|
|
|
ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), ..)
|
2018-12-16 16:18:45 +03:00
|
|
|
| ty::Foreign(def_id)
|
|
|
|
|
| ty::FnDef(def_id, ..)
|
|
|
|
|
| ty::Closure(def_id, ..)
|
2024-01-24 18:01:56 +00:00
|
|
|
| ty::CoroutineClosure(def_id, ..)
|
2023-10-19 16:06:43 +00:00
|
|
|
| ty::Coroutine(def_id, ..) => {
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(self.def_id_visitor.visit_def_id(def_id, "type", &ty));
|
2023-06-15 17:15:24 +03:00
|
|
|
if V::SHALLOW {
|
2024-02-24 17:22:28 -05:00
|
|
|
return V::Result::output();
|
2019-01-05 23:46:04 +03:00
|
|
|
}
|
2018-12-31 03:02:40 +03:00
|
|
|
// Default type visitor doesn't visit signatures of fn types.
|
|
|
|
|
// Something like `fn() -> Priv {my_func}` is considered a private type even if
|
|
|
|
|
// `my_func` is public, so we need to visit signatures.
|
2020-08-03 00:49:11 +02:00
|
|
|
if let ty::FnDef(..) = ty.kind() {
|
2023-07-11 22:35:29 +01:00
|
|
|
// FIXME: this should probably use `args` from `FnDef`
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(tcx.fn_sig(def_id).instantiate_identity().visit_with(self));
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
2023-07-11 22:35:29 +01:00
|
|
|
// Inherent static methods don't have self type in args.
|
2018-12-31 03:02:40 +03:00
|
|
|
// Something like `fn() {my_method}` type of the method
|
|
|
|
|
// `impl Pub<Priv> { pub fn my_method() {} }` is considered a private type,
|
|
|
|
|
// so we need to visit the self type additionally.
|
2018-12-16 16:18:45 +03:00
|
|
|
if let Some(assoc_item) = tcx.opt_associated_item(def_id) {
|
2022-03-13 00:52:25 +01:00
|
|
|
if let Some(impl_def_id) = assoc_item.impl_container(tcx) {
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(
|
|
|
|
|
tcx.type_of(impl_def_id).instantiate_identity().visit_with(self)
|
|
|
|
|
);
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-07-12 10:18:30 +00:00
|
|
|
ty::Alias(kind @ (ty::Inherent | ty::Weak | ty::Projection), data) => {
|
2023-06-15 17:15:24 +03:00
|
|
|
if V::SKIP_ASSOC_TYS {
|
2023-03-21 01:46:52 +01:00
|
|
|
// Visitors searching for minimal visibility/reachability want to
|
|
|
|
|
// conservatively approximate associated types like `Type::Alias`
|
|
|
|
|
// as visible/reachable even if `Type` is private.
|
2024-02-12 15:39:32 +09:00
|
|
|
// Ideally, associated types should be instantiated in the same way as
|
2023-03-21 01:46:52 +01:00
|
|
|
// free type aliases, but this isn't done yet.
|
2024-02-24 17:22:28 -05:00
|
|
|
return V::Result::output();
|
2023-03-21 01:46:52 +01:00
|
|
|
}
|
|
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(self.def_id_visitor.visit_def_id(
|
2023-03-21 01:46:52 +01:00
|
|
|
data.def_id,
|
2023-12-07 17:06:08 +00:00
|
|
|
match kind {
|
|
|
|
|
ty::Inherent | ty::Projection => "associated type",
|
|
|
|
|
ty::Weak => "type alias",
|
|
|
|
|
ty::Opaque => unreachable!(),
|
|
|
|
|
},
|
2023-03-21 01:46:52 +01:00
|
|
|
&LazyDefPathStr { def_id: data.def_id, tcx },
|
2024-02-24 17:22:28 -05:00
|
|
|
));
|
2023-03-21 01:46:52 +01:00
|
|
|
|
2023-07-11 22:35:29 +01:00
|
|
|
// This will also visit args if necessary, so we don't need to recurse.
|
2023-06-15 17:15:24 +03:00
|
|
|
return if V::SHALLOW {
|
2024-02-24 17:22:28 -05:00
|
|
|
V::Result::output()
|
2023-12-07 17:06:08 +00:00
|
|
|
} else if kind == ty::Projection {
|
2024-05-13 10:00:38 -04:00
|
|
|
self.visit_projection_term(data.into())
|
2023-03-21 01:46:52 +01:00
|
|
|
} else {
|
2024-02-24 17:22:28 -05:00
|
|
|
V::Result::from_branch(
|
|
|
|
|
data.args.iter().try_for_each(|arg| arg.visit_with(self).branch()),
|
|
|
|
|
)
|
2023-03-21 01:46:52 +01:00
|
|
|
};
|
|
|
|
|
}
|
2018-12-16 16:18:45 +03:00
|
|
|
ty::Dynamic(predicates, ..) => {
|
2019-01-05 23:46:04 +03:00
|
|
|
// All traits in the list are considered the "primary" part of the type
|
|
|
|
|
// and are visited by shallow visitors.
|
2020-12-11 15:02:46 -05:00
|
|
|
for predicate in predicates {
|
|
|
|
|
let trait_ref = match predicate.skip_binder() {
|
2018-12-31 03:02:40 +03:00
|
|
|
ty::ExistentialPredicate::Trait(trait_ref) => trait_ref,
|
|
|
|
|
ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx),
|
|
|
|
|
ty::ExistentialPredicate::AutoTrait(def_id) => {
|
2024-09-30 01:00:38 -04:00
|
|
|
ty::ExistentialTraitRef::new(tcx, def_id, ty::GenericArgs::empty())
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2018-12-16 16:18:45 +03:00
|
|
|
};
|
2024-09-30 01:00:38 -04:00
|
|
|
let ty::ExistentialTraitRef { def_id, .. } = trait_ref;
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref));
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
}
|
2022-12-13 11:07:42 +00:00
|
|
|
ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
|
2018-12-16 16:18:45 +03:00
|
|
|
// Skip repeated `Opaque`s to avoid infinite recursion.
|
|
|
|
|
if self.visited_opaque_tys.insert(def_id) {
|
2019-01-05 23:46:04 +03:00
|
|
|
// The intent is to treat `impl Trait1 + Trait2` identically to
|
|
|
|
|
// `dyn Trait1 + Trait2`. Therefore we ignore def-id of the opaque type itself
|
|
|
|
|
// (it either has no visibility, or its visibility is insignificant, like
|
2020-06-27 21:36:35 +01:00
|
|
|
// visibilities of type aliases) and recurse into bounds instead to go
|
2019-01-05 23:46:04 +03:00
|
|
|
// through the trait list (default type visitor doesn't visit those traits).
|
|
|
|
|
// All traits in the list are considered the "primary" part of the type
|
|
|
|
|
// and are visited by shallow visitors.
|
2024-02-24 17:22:28 -05:00
|
|
|
try_visit!(self.visit_clauses(tcx.explicit_item_bounds(def_id).skip_binder()));
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// These types don't have their own def-ids (but may have subcomponents
|
|
|
|
|
// with def-ids that should be visited recursively).
|
|
|
|
|
ty::Bool
|
|
|
|
|
| ty::Char
|
|
|
|
|
| ty::Int(..)
|
|
|
|
|
| ty::Uint(..)
|
|
|
|
|
| ty::Float(..)
|
|
|
|
|
| ty::Str
|
|
|
|
|
| ty::Never
|
|
|
|
|
| ty::Array(..)
|
|
|
|
|
| ty::Slice(..)
|
|
|
|
|
| ty::Tuple(..)
|
|
|
|
|
| ty::RawPtr(..)
|
|
|
|
|
| ty::Ref(..)
|
2023-02-02 13:57:36 +00:00
|
|
|
| ty::Pat(..)
|
2018-12-16 16:18:45 +03:00
|
|
|
| ty::FnPtr(..)
|
2024-12-21 17:05:40 +00:00
|
|
|
| ty::UnsafeBinder(_)
|
2018-12-16 16:18:45 +03:00
|
|
|
| ty::Param(..)
|
2023-02-06 23:53:24 +00:00
|
|
|
| ty::Bound(..)
|
2020-05-05 23:02:09 -05:00
|
|
|
| ty::Error(_)
|
2023-10-19 16:06:43 +00:00
|
|
|
| ty::CoroutineWitness(..) => {}
|
2023-02-06 23:53:24 +00:00
|
|
|
ty::Placeholder(..) | ty::Infer(..) => {
|
2018-12-16 16:18:45 +03:00
|
|
|
bug!("unexpected type: {:?}", ty)
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
if V::SHALLOW { V::Result::output() } else { ty.super_visit_with(self) }
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
2020-11-22 09:37:37 +00:00
|
|
|
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_const(&mut self, c: Const<'tcx>) -> Self::Result {
|
2020-11-22 09:37:37 +00:00
|
|
|
let tcx = self.def_id_visitor.tcx();
|
2022-11-24 11:09:15 +00:00
|
|
|
tcx.expand_abstract_consts(c).super_visit_with(self)
|
2020-11-22 09:37:37 +00:00
|
|
|
}
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
|
2019-06-21 20:27:44 +02:00
|
|
|
fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visibility {
|
2018-12-16 16:18:45 +03:00
|
|
|
if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// Visitor used to determine impl visibility and reachability.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-06-15 17:15:24 +03:00
|
|
|
struct FindMin<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> {
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2022-09-22 16:19:53 +03:00
|
|
|
effective_visibilities: &'a EffectiveVisibilities,
|
2018-12-31 03:02:40 +03:00
|
|
|
min: VL,
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-15 17:15:24 +03:00
|
|
|
impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
|
|
|
|
|
for FindMin<'a, 'tcx, VL, SHALLOW>
|
|
|
|
|
{
|
|
|
|
|
const SHALLOW: bool = SHALLOW;
|
|
|
|
|
const SKIP_ASSOC_TYS: bool = true;
|
2019-06-14 00:48:52 +03:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
|
|
|
|
self.tcx
|
|
|
|
|
}
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
|
2022-08-28 00:10:06 +03:00
|
|
|
if let Some(def_id) = def_id.as_local() {
|
|
|
|
|
self.min = VL::new_min(self, def_id);
|
|
|
|
|
}
|
2018-12-31 03:02:40 +03:00
|
|
|
}
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
|
2018-12-31 03:02:40 +03:00
|
|
|
trait VisibilityLike: Sized {
|
2018-12-16 16:18:45 +03:00
|
|
|
const MAX: Self;
|
2023-06-15 17:15:24 +03:00
|
|
|
fn new_min<const SHALLOW: bool>(
|
|
|
|
|
find: &FindMin<'_, '_, Self, SHALLOW>,
|
|
|
|
|
def_id: LocalDefId,
|
|
|
|
|
) -> Self;
|
2018-12-31 03:02:40 +03:00
|
|
|
|
2023-06-15 17:15:24 +03:00
|
|
|
// Returns an over-approximation (`SKIP_ASSOC_TYS` = true) of visibility due to
|
2018-12-31 03:02:40 +03:00
|
|
|
// associated types for which we can't determine visibility precisely.
|
2023-06-15 17:15:24 +03:00
|
|
|
fn of_impl<const SHALLOW: bool>(
|
2022-09-22 16:19:53 +03:00
|
|
|
def_id: LocalDefId,
|
|
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
|
effective_visibilities: &EffectiveVisibilities,
|
|
|
|
|
) -> Self {
|
2023-06-15 17:15:24 +03:00
|
|
|
let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
|
2023-07-11 22:35:29 +01:00
|
|
|
find.visit(tcx.type_of(def_id).instantiate_identity());
|
2023-01-10 14:57:22 -07:00
|
|
|
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
|
2023-07-11 22:35:29 +01:00
|
|
|
find.visit_trait(trait_ref.instantiate_identity());
|
2018-12-31 03:02:40 +03:00
|
|
|
}
|
|
|
|
|
find.min
|
|
|
|
|
}
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
2023-06-19 17:06:00 +03:00
|
|
|
|
2018-12-31 03:02:40 +03:00
|
|
|
impl VisibilityLike for ty::Visibility {
|
2018-12-16 16:18:45 +03:00
|
|
|
const MAX: Self = ty::Visibility::Public;
|
2023-06-15 17:15:24 +03:00
|
|
|
fn new_min<const SHALLOW: bool>(
|
|
|
|
|
find: &FindMin<'_, '_, Self, SHALLOW>,
|
|
|
|
|
def_id: LocalDefId,
|
|
|
|
|
) -> Self {
|
2022-08-28 00:10:06 +03:00
|
|
|
min(find.tcx.local_visibility(def_id), find.min, find.tcx)
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
}
|
2023-05-10 15:35:00 +03:00
|
|
|
|
2023-06-15 17:15:24 +03:00
|
|
|
impl VisibilityLike for EffectiveVisibility {
|
|
|
|
|
const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public);
|
|
|
|
|
fn new_min<const SHALLOW: bool>(
|
|
|
|
|
find: &FindMin<'_, '_, Self, SHALLOW>,
|
|
|
|
|
def_id: LocalDefId,
|
|
|
|
|
) -> Self {
|
2023-06-06 18:26:38 +03:00
|
|
|
let effective_vis =
|
2023-06-15 17:15:24 +03:00
|
|
|
find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| {
|
2023-04-26 20:53:51 +02:00
|
|
|
let private_vis = ty::Visibility::Restricted(
|
|
|
|
|
find.tcx.parent_module_from_def_id(def_id).to_local_def_id(),
|
|
|
|
|
);
|
2023-06-06 18:26:38 +03:00
|
|
|
EffectiveVisibility::from_vis(private_vis)
|
|
|
|
|
});
|
|
|
|
|
|
2023-06-15 17:15:24 +03:00
|
|
|
effective_vis.min(find.min, find.tcx)
|
2018-12-16 16:18:45 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-15 10:47:17 -08:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2019-02-08 14:53:55 +01:00
|
|
|
/// The embargo visitor, used to determine the exports of the AST.
|
2015-01-15 10:47:17 -08:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2019-06-11 22:03:44 +03:00
|
|
|
struct EmbargoVisitor<'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2015-01-15 10:47:17 -08:00
|
|
|
|
2022-09-22 16:19:53 +03:00
|
|
|
/// Effective visibilities for reachable nodes.
|
|
|
|
|
effective_visibilities: EffectiveVisibilities,
|
2019-08-05 23:06:02 +01:00
|
|
|
/// A set of pairs corresponding to modules, where the first module is
|
|
|
|
|
/// reachable via a macro that's defined in the second module. This cannot
|
|
|
|
|
/// be represented as reachable because it can't handle the following case:
|
|
|
|
|
///
|
|
|
|
|
/// pub mod n { // Should be `Public`
|
|
|
|
|
/// pub(crate) mod p { // Should *not* be accessible
|
|
|
|
|
/// pub fn f() -> i32 { 12 } // Must be `Reachable`
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
/// pub macro m() {
|
|
|
|
|
/// n::p::f()
|
|
|
|
|
/// }
|
2023-04-26 20:53:51 +02:00
|
|
|
macro_reachable: FxHashSet<(LocalModDefId, LocalModDefId)>,
|
2019-08-05 23:06:02 +01:00
|
|
|
/// Has something changed in the level map?
|
2015-11-19 14:16:35 +03:00
|
|
|
changed: bool,
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
|
2019-06-11 22:03:44 +03:00
|
|
|
struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
|
2023-05-05 18:28:28 +03:00
|
|
|
effective_vis: EffectiveVisibility,
|
2021-08-14 20:51:49 +03:00
|
|
|
item_def_id: LocalDefId,
|
2019-06-11 22:03:44 +03:00
|
|
|
ev: &'a mut EmbargoVisitor<'tcx>,
|
2023-05-10 15:35:00 +03:00
|
|
|
level: Level,
|
2016-02-14 00:04:17 +03:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 12:38:06 -05:00
|
|
|
impl<'tcx> EmbargoVisitor<'tcx> {
|
2023-05-10 15:35:00 +03:00
|
|
|
fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
|
|
|
|
|
self.effective_visibilities.effective_vis(def_id).copied()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Updates node effective visibility.
|
|
|
|
|
fn update(
|
|
|
|
|
&mut self,
|
|
|
|
|
def_id: LocalDefId,
|
2023-05-05 19:33:02 +03:00
|
|
|
inherited_effective_vis: EffectiveVisibility,
|
2023-05-10 15:35:00 +03:00
|
|
|
level: Level,
|
|
|
|
|
) {
|
|
|
|
|
let nominal_vis = self.tcx.local_visibility(def_id);
|
|
|
|
|
self.update_eff_vis(def_id, inherited_effective_vis, Some(nominal_vis), level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn update_eff_vis(
|
|
|
|
|
&mut self,
|
|
|
|
|
def_id: LocalDefId,
|
2023-05-05 19:33:02 +03:00
|
|
|
inherited_effective_vis: EffectiveVisibility,
|
2023-06-15 20:43:20 +03:00
|
|
|
max_vis: Option<ty::Visibility>,
|
2023-05-10 15:35:00 +03:00
|
|
|
level: Level,
|
|
|
|
|
) {
|
2023-04-26 20:53:51 +02:00
|
|
|
// FIXME(typed_def_id): Make `Visibility::Restricted` use a `LocalModDefId` by default.
|
|
|
|
|
let private_vis =
|
|
|
|
|
ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id).into());
|
2023-06-15 20:43:20 +03:00
|
|
|
if max_vis != Some(private_vis) {
|
2023-05-05 19:33:02 +03:00
|
|
|
self.changed |= self.effective_visibilities.update(
|
|
|
|
|
def_id,
|
2023-06-15 20:43:20 +03:00
|
|
|
max_vis,
|
2023-05-05 19:33:02 +03:00
|
|
|
|| private_vis,
|
|
|
|
|
inherited_effective_vis,
|
|
|
|
|
level,
|
|
|
|
|
self.tcx,
|
|
|
|
|
);
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
2015-10-25 04:42:31 +03:00
|
|
|
}
|
2016-02-14 00:04:17 +03:00
|
|
|
|
2019-06-12 00:11:55 +03:00
|
|
|
fn reach(
|
|
|
|
|
&mut self,
|
2021-08-14 20:51:49 +03:00
|
|
|
def_id: LocalDefId,
|
2023-05-05 18:28:28 +03:00
|
|
|
effective_vis: EffectiveVisibility,
|
2019-06-12 00:11:55 +03:00
|
|
|
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
2016-11-28 05:09:28 +02:00
|
|
|
ReachEverythingInTheInterfaceVisitor {
|
2023-05-10 15:35:00 +03:00
|
|
|
effective_vis,
|
2021-08-14 20:51:49 +03:00
|
|
|
item_def_id: def_id,
|
2016-11-28 05:09:28 +02:00
|
|
|
ev: self,
|
2023-05-10 15:35:00 +03:00
|
|
|
level: Level::Reachable,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn reach_through_impl_trait(
|
|
|
|
|
&mut self,
|
|
|
|
|
def_id: LocalDefId,
|
2023-05-05 18:28:28 +03:00
|
|
|
effective_vis: EffectiveVisibility,
|
2023-05-10 15:35:00 +03:00
|
|
|
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
|
|
|
|
ReachEverythingInTheInterfaceVisitor {
|
|
|
|
|
effective_vis,
|
|
|
|
|
item_def_id: def_id,
|
|
|
|
|
ev: self,
|
|
|
|
|
level: Level::ReachableThroughImplTrait,
|
2016-11-28 05:09:28 +02:00
|
|
|
}
|
2016-02-14 00:04:17 +03:00
|
|
|
}
|
2019-01-26 20:30:52 +01:00
|
|
|
|
2021-07-30 23:50:57 -07:00
|
|
|
// We have to make sure that the items that macros might reference
|
|
|
|
|
// are reachable, since they might be exported transitively.
|
2023-05-05 19:33:02 +03:00
|
|
|
fn update_reachability_from_macro(
|
|
|
|
|
&mut self,
|
|
|
|
|
local_def_id: LocalDefId,
|
|
|
|
|
md: &MacroDef,
|
|
|
|
|
macro_ev: EffectiveVisibility,
|
|
|
|
|
) {
|
2021-07-30 23:50:57 -07:00
|
|
|
// Non-opaque macros cannot make other items more accessible than they already are.
|
2023-11-24 19:28:19 +03:00
|
|
|
let hir_id = self.tcx.local_def_id_to_hir_id(local_def_id);
|
2025-02-21 18:33:05 +11:00
|
|
|
let attrs = self.tcx.hir_attrs(hir_id);
|
2025-02-09 22:49:33 +01:00
|
|
|
|
|
|
|
|
if attr::find_attr!(attrs, AttributeKind::MacroTransparency(x) => *x)
|
|
|
|
|
.unwrap_or(Transparency::fallback(md.macro_rules))
|
|
|
|
|
!= Transparency::Opaque
|
|
|
|
|
{
|
2021-07-30 23:50:57 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-25 22:08:45 +03:00
|
|
|
let macro_module_def_id = self.tcx.local_parent(local_def_id);
|
2023-11-24 00:49:02 +03:00
|
|
|
if self.tcx.def_kind(macro_module_def_id) != DefKind::Mod {
|
2021-07-30 23:50:57 -07:00
|
|
|
// The macro's parent doesn't correspond to a `mod`, return early (#63164, #65252).
|
|
|
|
|
return;
|
|
|
|
|
}
|
2023-04-26 20:53:51 +02:00
|
|
|
// FIXME(typed_def_id): Introduce checked constructors that check def_kind.
|
|
|
|
|
let macro_module_def_id = LocalModDefId::new_unchecked(macro_module_def_id);
|
2021-07-30 23:50:57 -07:00
|
|
|
|
2023-05-10 15:35:00 +03:00
|
|
|
if self.effective_visibilities.public_at_level(local_def_id).is_none() {
|
2021-07-30 23:50:57 -07:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Since we are starting from an externally visible module,
|
|
|
|
|
// all the parents in the loop below are also guaranteed to be modules.
|
|
|
|
|
let mut module_def_id = macro_module_def_id;
|
|
|
|
|
loop {
|
|
|
|
|
let changed_reachability =
|
2023-05-10 15:35:00 +03:00
|
|
|
self.update_macro_reachable(module_def_id, macro_module_def_id, macro_ev);
|
2023-04-26 20:53:05 +02:00
|
|
|
if changed_reachability || module_def_id == LocalModDefId::CRATE_DEF_ID {
|
2021-07-30 23:50:57 -07:00
|
|
|
break;
|
|
|
|
|
}
|
2023-04-26 20:53:51 +02:00
|
|
|
module_def_id = LocalModDefId::new_unchecked(self.tcx.local_parent(module_def_id));
|
2021-07-30 23:50:57 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-05 23:06:02 +01:00
|
|
|
/// Updates the item as being reachable through a macro defined in the given
|
|
|
|
|
/// module. Returns `true` if the level has changed.
|
2021-07-28 18:23:40 +03:00
|
|
|
fn update_macro_reachable(
|
|
|
|
|
&mut self,
|
2023-04-26 20:53:51 +02:00
|
|
|
module_def_id: LocalModDefId,
|
|
|
|
|
defining_mod: LocalModDefId,
|
2023-05-05 18:28:28 +03:00
|
|
|
macro_ev: EffectiveVisibility,
|
2021-07-28 18:23:40 +03:00
|
|
|
) -> bool {
|
|
|
|
|
if self.macro_reachable.insert((module_def_id, defining_mod)) {
|
2023-12-06 15:15:15 +03:00
|
|
|
for child in self.tcx.module_children_local(module_def_id.to_local_def_id()) {
|
|
|
|
|
if let Res::Def(def_kind, def_id) = child.res
|
|
|
|
|
&& let Some(def_id) = def_id.as_local()
|
|
|
|
|
&& child.vis.is_accessible_from(defining_mod, self.tcx)
|
|
|
|
|
{
|
|
|
|
|
let vis = self.tcx.local_visibility(def_id);
|
|
|
|
|
self.update_macro_reachable_def(def_id, def_kind, vis, defining_mod, macro_ev);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-08-05 23:06:02 +01:00
|
|
|
true
|
|
|
|
|
} else {
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn update_macro_reachable_def(
|
|
|
|
|
&mut self,
|
2021-07-28 18:23:40 +03:00
|
|
|
def_id: LocalDefId,
|
2019-08-05 23:06:02 +01:00
|
|
|
def_kind: DefKind,
|
|
|
|
|
vis: ty::Visibility,
|
2023-04-26 20:53:51 +02:00
|
|
|
module: LocalModDefId,
|
2023-05-05 18:28:28 +03:00
|
|
|
macro_ev: EffectiveVisibility,
|
2019-08-05 23:06:02 +01:00
|
|
|
) {
|
2023-05-05 19:33:02 +03:00
|
|
|
self.update(def_id, macro_ev, Level::Reachable);
|
2019-08-05 23:06:02 +01:00
|
|
|
match def_kind {
|
|
|
|
|
// No type privacy, so can be directly marked as reachable.
|
2024-02-23 23:12:20 +00:00
|
|
|
DefKind::Const | DefKind::Static { .. } | DefKind::TraitAlias | DefKind::TyAlias => {
|
2022-08-28 00:10:06 +03:00
|
|
|
if vis.is_accessible_from(module, self.tcx) {
|
2023-05-05 19:33:02 +03:00
|
|
|
self.update(def_id, macro_ev, Level::Reachable);
|
2019-08-05 23:06:02 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-30 15:14:15 -04:00
|
|
|
// Hygiene isn't really implemented for `macro_rules!` macros at the
|
2021-07-30 23:50:57 -07:00
|
|
|
// moment. Accordingly, marking them as reachable is unwise. `macro` macros
|
2022-03-30 15:14:15 -04:00
|
|
|
// have normal hygiene, so we can treat them like other items without type
|
2021-07-30 23:50:57 -07:00
|
|
|
// privacy and mark them reachable.
|
|
|
|
|
DefKind::Macro(_) => {
|
2025-02-21 18:33:05 +11:00
|
|
|
let item = self.tcx.hir_expect_item(def_id);
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
if let hir::ItemKind::Macro(_, MacroDef { macro_rules: false, .. }, _) = item.kind {
|
2022-08-28 00:10:06 +03:00
|
|
|
if vis.is_accessible_from(module, self.tcx) {
|
2023-05-05 19:33:02 +03:00
|
|
|
self.update(def_id, macro_ev, Level::Reachable);
|
2021-07-30 23:50:57 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-05 23:06:02 +01:00
|
|
|
// We can't use a module name as the final segment of a path, except
|
|
|
|
|
// in use statements. Since re-export checking doesn't consider
|
|
|
|
|
// hygiene these don't need to be marked reachable. The contents of
|
|
|
|
|
// the module, however may be reachable.
|
|
|
|
|
DefKind::Mod => {
|
2022-08-28 00:10:06 +03:00
|
|
|
if vis.is_accessible_from(module, self.tcx) {
|
2023-04-26 20:53:51 +02:00
|
|
|
self.update_macro_reachable(
|
|
|
|
|
LocalModDefId::new_unchecked(def_id),
|
|
|
|
|
module,
|
|
|
|
|
macro_ev,
|
|
|
|
|
);
|
2019-08-05 23:06:02 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DefKind::Struct | DefKind::Union => {
|
2021-07-28 18:23:40 +03:00
|
|
|
// While structs and unions have type privacy, their fields do not.
|
2025-02-21 18:33:05 +11:00
|
|
|
let item = self.tcx.hir_expect_item(def_id);
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
if let hir::ItemKind::Struct(_, ref struct_def, _)
|
|
|
|
|
| hir::ItemKind::Union(_, ref struct_def, _) = item.kind
|
2023-05-10 15:35:00 +03:00
|
|
|
{
|
|
|
|
|
for field in struct_def.fields() {
|
|
|
|
|
let field_vis = self.tcx.local_visibility(field.def_id);
|
|
|
|
|
if field_vis.is_accessible_from(module, self.tcx) {
|
|
|
|
|
self.reach(field.def_id, macro_ev).ty();
|
2019-08-05 23:06:02 +01:00
|
|
|
}
|
|
|
|
|
}
|
2023-05-10 15:35:00 +03:00
|
|
|
} else {
|
|
|
|
|
bug!("item {:?} with DefKind {:?}", item, def_kind);
|
2019-08-05 23:06:02 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-17 16:55:08 +03:00
|
|
|
// These have type privacy, so are not reachable unless they're
|
|
|
|
|
// public, or are not namespaced at all.
|
2019-08-05 23:06:02 +01:00
|
|
|
DefKind::AssocConst
|
|
|
|
|
| DefKind::AssocTy
|
|
|
|
|
| DefKind::ConstParam
|
|
|
|
|
| DefKind::Ctor(_, _)
|
|
|
|
|
| DefKind::Enum
|
|
|
|
|
| DefKind::ForeignTy
|
|
|
|
|
| DefKind::Fn
|
|
|
|
|
| DefKind::OpaqueTy
|
2020-03-03 12:29:07 -06:00
|
|
|
| DefKind::AssocFn
|
2019-08-05 23:06:02 +01:00
|
|
|
| DefKind::Trait
|
|
|
|
|
| DefKind::TyParam
|
2020-03-16 10:01:03 -05:00
|
|
|
| DefKind::Variant
|
|
|
|
|
| DefKind::LifetimeParam
|
|
|
|
|
| DefKind::ExternCrate
|
|
|
|
|
| DefKind::Use
|
|
|
|
|
| DefKind::ForeignMod
|
|
|
|
|
| DefKind::AnonConst
|
2021-10-02 12:59:26 +01:00
|
|
|
| DefKind::InlineConst
|
2020-03-16 10:01:03 -05:00
|
|
|
| DefKind::Field
|
|
|
|
|
| DefKind::GlobalAsm
|
2023-02-12 18:26:47 +00:00
|
|
|
| DefKind::Impl { .. }
|
2024-08-01 13:05:17 -04:00
|
|
|
| DefKind::Closure
|
|
|
|
|
| DefKind::SyntheticCoroutineBody => (),
|
2019-08-05 23:06:02 +01:00
|
|
|
}
|
|
|
|
|
}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 12:38:06 -05:00
|
|
|
impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
|
2024-08-09 20:43:30 -07:00
|
|
|
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
2023-05-05 19:33:02 +03:00
|
|
|
// Update levels of nested things and mark all items
|
|
|
|
|
// in interfaces of reachable items as reachable.
|
|
|
|
|
let item_ev = self.get(item.owner_id.def_id);
|
2022-01-11 20:09:31 +00:00
|
|
|
match item.kind {
|
2023-05-05 19:33:02 +03:00
|
|
|
// The interface is empty, and no nested items.
|
|
|
|
|
hir::ItemKind::Use(..)
|
|
|
|
|
| hir::ItemKind::ExternCrate(..)
|
2025-02-17 05:33:06 +00:00
|
|
|
| hir::ItemKind::GlobalAsm { .. } => {}
|
2023-05-05 19:33:02 +03:00
|
|
|
// The interface is empty, and all nested items are processed by `visit_item`.
|
2024-08-09 20:43:30 -07:00
|
|
|
hir::ItemKind::Mod(..) => {}
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
hir::ItemKind::Macro(_, macro_def, _) => {
|
2023-05-05 19:33:02 +03:00
|
|
|
if let Some(item_ev) = item_ev {
|
|
|
|
|
self.update_reachability_from_macro(item.owner_id.def_id, macro_def, item_ev);
|
2022-01-11 20:09:31 +00:00
|
|
|
}
|
|
|
|
|
}
|
2018-07-11 23:36:06 +08:00
|
|
|
hir::ItemKind::Const(..)
|
|
|
|
|
| hir::ItemKind::Static(..)
|
2025-01-04 11:30:31 +01:00
|
|
|
| hir::ItemKind::Fn { .. }
|
2019-08-02 11:02:08 +01:00
|
|
|
| hir::ItemKind::TyAlias(..) => {
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(item_ev) = item_ev {
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty();
|
2016-11-28 05:09:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
2019-11-28 19:28:50 +01:00
|
|
|
hir::ItemKind::Trait(.., trait_item_refs) => {
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(item_ev) = item_ev {
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
|
2016-11-28 05:09:28 +02:00
|
|
|
|
2016-12-04 04:21:06 +02:00
|
|
|
for trait_item_ref in trait_item_refs {
|
2023-05-05 19:33:02 +03:00
|
|
|
self.update(trait_item_ref.id.owner_id.def_id, item_ev, Level::Reachable);
|
|
|
|
|
|
2022-03-12 19:36:11 +01:00
|
|
|
let tcx = self.tcx;
|
2023-05-10 15:35:00 +03:00
|
|
|
let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_ev);
|
2016-11-28 05:09:28 +02:00
|
|
|
reach.generics().predicates();
|
|
|
|
|
|
2019-05-19 16:26:08 +08:00
|
|
|
if trait_item_ref.kind == AssocItemKind::Type
|
2023-06-01 06:14:06 +00:00
|
|
|
&& !tcx.defaultness(trait_item_ref.id.owner_id).has_value()
|
2016-12-04 04:21:06 +02:00
|
|
|
{
|
2016-11-28 05:09:28 +02:00
|
|
|
// No type to visit.
|
|
|
|
|
} else {
|
2017-04-24 15:20:46 +03:00
|
|
|
reach.ty();
|
2016-11-28 05:09:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-07-11 23:36:06 +08:00
|
|
|
hir::ItemKind::TraitAlias(..) => {
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(item_ev) = item_ev {
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
|
2017-10-02 12:28:16 +00:00
|
|
|
}
|
|
|
|
|
}
|
2023-11-21 20:07:32 +01:00
|
|
|
hir::ItemKind::Impl(impl_) => {
|
2023-06-15 17:15:24 +03:00
|
|
|
// Type inference is very smart sometimes. It can make an impl reachable even some
|
|
|
|
|
// components of its type or trait are unreachable. E.g. methods of
|
|
|
|
|
// `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
|
2023-07-11 22:35:29 +01:00
|
|
|
// can be usable from other crates (#57264). So we skip args when calculating
|
2023-06-15 17:15:24 +03:00
|
|
|
// reachability and consider an impl reachable if its "shallow" type and trait are
|
|
|
|
|
// reachable.
|
|
|
|
|
//
|
|
|
|
|
// The assumption we make here is that type-inference won't let you use an impl
|
|
|
|
|
// without knowing both "shallow" version of its self type and "shallow" version of
|
|
|
|
|
// its trait if it exists (which require reaching the `DefId`s in them).
|
|
|
|
|
let item_ev = EffectiveVisibility::of_impl::<true>(
|
2023-05-05 19:33:02 +03:00
|
|
|
item.owner_id.def_id,
|
|
|
|
|
self.tcx,
|
|
|
|
|
&self.effective_visibilities,
|
2023-06-15 17:15:24 +03:00
|
|
|
);
|
2023-05-18 14:57:45 +03:00
|
|
|
|
2023-06-06 18:26:38 +03:00
|
|
|
self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct);
|
|
|
|
|
|
|
|
|
|
self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty().trait_ref();
|
|
|
|
|
|
|
|
|
|
for impl_item_ref in impl_.items {
|
|
|
|
|
let def_id = impl_item_ref.id.owner_id.def_id;
|
2023-06-15 20:43:20 +03:00
|
|
|
let max_vis =
|
2023-06-06 18:26:38 +03:00
|
|
|
impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
|
2023-06-15 20:43:20 +03:00
|
|
|
self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);
|
2023-06-06 18:26:38 +03:00
|
|
|
|
|
|
|
|
if let Some(impl_item_ev) = self.get(def_id) {
|
|
|
|
|
self.reach(def_id, impl_item_ev).generics().predicates().ty();
|
2016-11-28 05:09:28 +02:00
|
|
|
}
|
2016-02-14 00:04:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
hir::ItemKind::Enum(_, ref def, _) => {
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(item_ev) = item_ev {
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
|
2016-02-14 00:04:17 +03:00
|
|
|
}
|
2019-11-29 09:26:18 +01:00
|
|
|
for variant in def.variants {
|
2023-05-05 19:33:02 +03:00
|
|
|
if let Some(item_ev) = item_ev {
|
|
|
|
|
self.update(variant.def_id, item_ev, Level::Reachable);
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(variant_ev) = self.get(variant.def_id) {
|
2023-05-05 19:33:02 +03:00
|
|
|
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
|
|
|
|
|
self.update(ctor_def_id, variant_ev, Level::Reachable);
|
|
|
|
|
}
|
2019-08-13 21:40:21 -03:00
|
|
|
for field in variant.data.fields() {
|
2023-05-05 19:33:02 +03:00
|
|
|
self.update(field.def_id, variant_ev, Level::Reachable);
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(field.def_id, variant_ev).ty();
|
2016-02-14 00:04:17 +03:00
|
|
|
}
|
|
|
|
|
// Corner case: if the variant is reachable, but its
|
|
|
|
|
// enum is not, make the enum reachable as well.
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(item.owner_id.def_id, variant_ev).ty();
|
2022-05-17 00:00:00 +00:00
|
|
|
}
|
2022-11-06 19:46:55 +00:00
|
|
|
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(ctor_ev) = self.get(ctor_def_id) {
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(item.owner_id.def_id, ctor_ev).ty();
|
2022-05-17 00:00:00 +00:00
|
|
|
}
|
2016-02-14 00:04:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-11 22:40:09 +01:00
|
|
|
hir::ItemKind::ForeignMod { items, .. } => {
|
|
|
|
|
for foreign_item in items {
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(foreign_item_ev) = self.get(foreign_item.id.owner_id.def_id) {
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(foreign_item.id.owner_id.def_id, foreign_item_ev)
|
2018-12-16 16:18:45 +03:00
|
|
|
.generics()
|
|
|
|
|
.predicates()
|
|
|
|
|
.ty();
|
2016-02-14 00:04:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
hir::ItemKind::Struct(_, ref struct_def, _)
|
|
|
|
|
| hir::ItemKind::Union(_, ref struct_def, _) => {
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(item_ev) = item_ev {
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(item.owner_id.def_id, item_ev).generics().predicates();
|
2016-02-14 00:04:17 +03:00
|
|
|
for field in struct_def.fields() {
|
2023-05-05 19:33:02 +03:00
|
|
|
self.update(field.def_id, item_ev, Level::Reachable);
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(field_ev) = self.get(field.def_id) {
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(field.def_id, field_ev).ty();
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-11-06 19:46:55 +00:00
|
|
|
if let Some(ctor_def_id) = struct_def.ctor_def_id() {
|
2023-05-05 19:33:02 +03:00
|
|
|
if let Some(item_ev) = item_ev {
|
|
|
|
|
self.update(ctor_def_id, item_ev, Level::Reachable);
|
|
|
|
|
}
|
2023-05-05 18:28:28 +03:00
|
|
|
if let Some(ctor_ev) = self.get(ctor_def_id) {
|
2023-05-10 15:35:00 +03:00
|
|
|
self.reach(item.owner_id.def_id, ctor_ev).ty();
|
2022-05-17 00:00:00 +00:00
|
|
|
}
|
|
|
|
|
}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-02-14 00:04:17 +03:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 12:38:06 -05:00
|
|
|
impl ReachEverythingInTheInterfaceVisitor<'_, '_> {
|
2016-11-28 05:09:28 +02:00
|
|
|
fn generics(&mut self) -> &mut Self {
|
2024-05-09 20:56:44 -04:00
|
|
|
for param in &self.ev.tcx.generics_of(self.item_def_id).own_params {
|
2024-11-11 18:41:27 +01:00
|
|
|
if let GenericParamDefKind::Const { .. } = param.kind {
|
|
|
|
|
self.visit(self.ev.tcx.type_of(param.def_id).instantiate_identity());
|
|
|
|
|
}
|
|
|
|
|
if let Some(default) = param.default_value(self.ev.tcx) {
|
|
|
|
|
self.visit(default.instantiate_identity());
|
2017-01-25 22:01:11 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-11-28 05:09:28 +02:00
|
|
|
self
|
2016-11-04 18:20:15 -04:00
|
|
|
}
|
|
|
|
|
|
2016-11-28 05:09:28 +02:00
|
|
|
fn predicates(&mut self) -> &mut Self {
|
2018-12-16 16:18:45 +03:00
|
|
|
self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id));
|
2016-11-28 05:09:28 +02:00
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-24 15:20:46 +03:00
|
|
|
fn ty(&mut self) -> &mut Self {
|
2023-07-11 22:35:29 +01:00
|
|
|
self.visit(self.ev.tcx.type_of(self.item_def_id).instantiate_identity());
|
2016-11-28 05:09:28 +02:00
|
|
|
self
|
|
|
|
|
}
|
2019-01-05 21:56:49 +03:00
|
|
|
|
|
|
|
|
fn trait_ref(&mut self) -> &mut Self {
|
2023-01-10 14:57:22 -07:00
|
|
|
if let Some(trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) {
|
2023-07-11 22:35:29 +01:00
|
|
|
self.visit_trait(trait_ref.instantiate_identity());
|
2019-01-05 21:56:49 +03:00
|
|
|
}
|
|
|
|
|
self
|
|
|
|
|
}
|
2016-11-28 05:09:28 +02:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 12:38:06 -05:00
|
|
|
impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
|
|
|
|
self.ev.tcx
|
|
|
|
|
}
|
2024-02-24 17:22:28 -05:00
|
|
|
fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) {
|
2020-04-12 13:45:41 +01:00
|
|
|
if let Some(def_id) = def_id.as_local() {
|
2023-06-15 19:07:51 +03:00
|
|
|
// All effective visibilities except `reachable_through_impl_trait` are limited to
|
|
|
|
|
// nominal visibility. If any type or trait is leaked farther than that, it will
|
|
|
|
|
// produce type privacy errors on any use, so we don't consider it leaked.
|
2023-06-15 20:43:20 +03:00
|
|
|
let max_vis = (self.level != Level::ReachableThroughImplTrait)
|
2023-06-15 19:07:51 +03:00
|
|
|
.then(|| self.ev.tcx.local_visibility(def_id));
|
2023-06-15 20:43:20 +03:00
|
|
|
self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level);
|
2016-02-14 00:04:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-08-14 17:05:17 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2022-09-22 16:19:53 +03:00
|
|
|
/// Visitor, used for EffectiveVisibilities table checking
|
2022-08-14 17:05:17 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
2024-09-12 09:25:11 +10:00
|
|
|
pub struct TestReachabilityVisitor<'a, 'tcx> {
|
2022-08-14 17:05:17 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2022-09-22 16:19:53 +03:00
|
|
|
effective_visibilities: &'a EffectiveVisibilities,
|
2022-08-14 17:05:17 +03:00
|
|
|
}
|
|
|
|
|
|
2024-09-12 09:25:11 +10:00
|
|
|
impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> {
|
2022-09-22 16:19:53 +03:00
|
|
|
fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) {
|
2023-03-13 18:54:05 +00:00
|
|
|
if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) {
|
2022-10-17 20:09:03 +03:00
|
|
|
let mut error_msg = String::new();
|
|
|
|
|
let span = self.tcx.def_span(def_id.to_def_id());
|
2022-09-22 16:19:53 +03:00
|
|
|
if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) {
|
|
|
|
|
for level in Level::all_levels() {
|
2023-12-01 10:25:40 +08:00
|
|
|
let vis_str = effective_vis.at_level(level).to_string(def_id, self.tcx);
|
2022-09-22 16:19:53 +03:00
|
|
|
if level != Level::Direct {
|
2022-09-25 14:25:02 +03:00
|
|
|
error_msg.push_str(", ");
|
2022-09-12 10:57:34 +03:00
|
|
|
}
|
2022-12-19 10:31:55 +01:00
|
|
|
error_msg.push_str(&format!("{level:?}: {vis_str}"));
|
2022-09-12 10:57:34 +03:00
|
|
|
}
|
2022-10-17 20:09:03 +03:00
|
|
|
} else {
|
|
|
|
|
error_msg.push_str("not in the table");
|
2022-09-12 10:57:34 +03:00
|
|
|
}
|
2023-12-18 22:21:37 +11:00
|
|
|
self.tcx.dcx().emit_err(ReportEffectiveVisibility { span, descr: error_msg });
|
2022-08-14 17:05:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-12 09:25:11 +10:00
|
|
|
impl<'a, 'tcx> Visitor<'tcx> for TestReachabilityVisitor<'a, 'tcx> {
|
2022-08-14 17:05:17 +03:00
|
|
|
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
|
2022-10-27 14:02:18 +11:00
|
|
|
self.effective_visibility_diagnostic(item.owner_id.def_id);
|
2022-08-14 17:05:17 +03:00
|
|
|
|
|
|
|
|
match item.kind {
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
hir::ItemKind::Enum(_, ref def, _) => {
|
2022-08-14 17:05:17 +03:00
|
|
|
for variant in def.variants.iter() {
|
2022-11-06 19:46:55 +00:00
|
|
|
self.effective_visibility_diagnostic(variant.def_id);
|
|
|
|
|
if let Some(ctor_def_id) = variant.data.ctor_def_id() {
|
2022-11-04 16:28:03 +04:00
|
|
|
self.effective_visibility_diagnostic(ctor_def_id);
|
|
|
|
|
}
|
2022-08-14 17:05:17 +03:00
|
|
|
for field in variant.data.fields() {
|
2022-11-06 19:46:55 +00:00
|
|
|
self.effective_visibility_diagnostic(field.def_id);
|
2022-08-14 17:05:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
hir::ItemKind::Struct(_, ref def, _) | hir::ItemKind::Union(_, ref def, _) => {
|
2022-11-06 19:46:55 +00:00
|
|
|
if let Some(ctor_def_id) = def.ctor_def_id() {
|
2022-11-04 16:28:03 +04:00
|
|
|
self.effective_visibility_diagnostic(ctor_def_id);
|
|
|
|
|
}
|
2022-08-14 17:05:17 +03:00
|
|
|
for field in def.fields() {
|
2022-11-06 19:46:55 +00:00
|
|
|
self.effective_visibility_diagnostic(field.def_id);
|
2022-08-14 17:05:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
|
2022-10-27 14:02:18 +11:00
|
|
|
self.effective_visibility_diagnostic(item.owner_id.def_id);
|
2022-08-14 17:05:17 +03:00
|
|
|
}
|
|
|
|
|
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
|
2022-10-27 14:02:18 +11:00
|
|
|
self.effective_visibility_diagnostic(item.owner_id.def_id);
|
2022-08-14 17:05:17 +03:00
|
|
|
}
|
|
|
|
|
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
|
2022-10-27 14:02:18 +11:00
|
|
|
self.effective_visibility_diagnostic(item.owner_id.def_id);
|
2022-08-14 17:05:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-16 21:19:24 +03:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// Name privacy visitor, checks privacy and reports violations.
|
|
|
|
|
/// Most of name privacy checks are performed during the main resolution phase,
|
|
|
|
|
/// or later in type checking when field accesses and associated items are resolved.
|
|
|
|
|
/// This pass performs remaining checks for fields in struct expressions and patterns.
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
2015-01-15 10:47:17 -08:00
|
|
|
|
2020-06-25 22:23:41 +03:00
|
|
|
struct NamePrivacyVisitor<'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2020-07-17 08:47:04 +00:00
|
|
|
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
|
2020-06-25 22:23:41 +03:00
|
|
|
impl<'tcx> NamePrivacyVisitor<'tcx> {
|
2020-07-17 08:47:04 +00:00
|
|
|
/// Gets the type-checking results for the current body.
|
2020-06-25 22:23:41 +03:00
|
|
|
/// As this will ICE if called outside bodies, only call when working with
|
|
|
|
|
/// `Expr` or `Pat` nodes (they are guaranteed to be found only in bodies).
|
|
|
|
|
#[track_caller]
|
2020-07-17 08:47:04 +00:00
|
|
|
fn typeck_results(&self) -> &'tcx ty::TypeckResults<'tcx> {
|
|
|
|
|
self.maybe_typeck_results
|
|
|
|
|
.expect("`NamePrivacyVisitor::typeck_results` called outside of body")
|
2020-06-25 22:23:41 +03:00
|
|
|
}
|
|
|
|
|
|
2018-02-08 15:48:16 -08:00
|
|
|
// Checks that a field in a struct constructor (expression or pattern) is accessible.
|
|
|
|
|
fn check_field(
|
|
|
|
|
&mut self,
|
2024-01-25 13:25:29 +03:00
|
|
|
hir_id: hir::HirId, // ID of the field use
|
2018-11-27 02:59:49 +00:00
|
|
|
use_ctxt: Span, // syntax context of the field name at the use site
|
2022-03-05 07:28:41 +11:00
|
|
|
def: ty::AdtDef<'tcx>, // definition of the struct or enum
|
2018-11-27 02:59:49 +00:00
|
|
|
field: &'tcx ty::FieldDef,
|
2025-01-18 20:07:05 +00:00
|
|
|
) -> bool {
|
2021-08-14 20:51:49 +03:00
|
|
|
if def.is_enum() {
|
2025-01-18 20:07:05 +00:00
|
|
|
return true;
|
2021-08-14 20:51:49 +03:00
|
|
|
}
|
|
|
|
|
|
2018-11-27 02:59:49 +00:00
|
|
|
// definition of the field
|
2025-03-11 14:14:08 +11:00
|
|
|
let ident = Ident::new(sym::dummy, use_ctxt);
|
|
|
|
|
let (_, def_id) = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id);
|
2025-01-18 20:07:05 +00:00
|
|
|
!field.vis.is_accessible_from(def_id, self.tcx)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Checks that a field in a struct constructor (expression or pattern) is accessible.
|
|
|
|
|
fn emit_unreachable_field_error(
|
|
|
|
|
&mut self,
|
|
|
|
|
fields: Vec<(Symbol, Span, bool /* field is present */)>,
|
|
|
|
|
def: ty::AdtDef<'tcx>, // definition of the struct or enum
|
|
|
|
|
update_syntax: Option<Span>,
|
|
|
|
|
struct_span: Span,
|
|
|
|
|
) {
|
|
|
|
|
if def.is_enum() || fields.is_empty() {
|
|
|
|
|
return;
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
2025-01-18 20:07:05 +00:00
|
|
|
|
|
|
|
|
// error[E0451]: fields `beta` and `gamma` of struct `Alpha` are private
|
|
|
|
|
// --> $DIR/visibility.rs:18:13
|
|
|
|
|
// |
|
|
|
|
|
// LL | let _x = Alpha {
|
|
|
|
|
// | ----- in this type # from `def`
|
|
|
|
|
// LL | beta: 0,
|
|
|
|
|
// | ^^^^^^^ private field # `fields.2` is `true`
|
|
|
|
|
// LL | ..
|
|
|
|
|
// | ^^ field `gamma` is private # `fields.2` is `false`
|
|
|
|
|
|
|
|
|
|
// Get the list of all private fields for the main message.
|
2025-01-31 20:36:44 +00:00
|
|
|
let Some(field_names) = listify(&fields[..], |(n, _, _)| format!("`{n}`")) else { return };
|
2025-01-18 20:07:05 +00:00
|
|
|
let span: MultiSpan = fields.iter().map(|(_, span, _)| *span).collect::<Vec<Span>>().into();
|
|
|
|
|
|
|
|
|
|
// Get the list of all private fields when pointing at the `..rest`.
|
|
|
|
|
let rest_field_names: Vec<_> =
|
|
|
|
|
fields.iter().filter(|(_, _, is_present)| !is_present).map(|(n, _, _)| n).collect();
|
|
|
|
|
let rest_len = rest_field_names.len();
|
2025-01-31 20:36:44 +00:00
|
|
|
let rest_field_names =
|
|
|
|
|
listify(&rest_field_names[..], |n| format!("`{n}`")).unwrap_or_default();
|
2025-01-18 20:07:05 +00:00
|
|
|
// Get all the labels for each field or `..rest` in the primary MultiSpan.
|
|
|
|
|
let labels = fields
|
|
|
|
|
.iter()
|
|
|
|
|
.filter(|(_, _, is_present)| *is_present)
|
|
|
|
|
.map(|(_, span, _)| FieldIsPrivateLabel::Other { span: *span })
|
|
|
|
|
.chain(update_syntax.iter().map(|span| FieldIsPrivateLabel::IsUpdateSyntax {
|
|
|
|
|
span: *span,
|
|
|
|
|
rest_field_names: rest_field_names.clone(),
|
|
|
|
|
rest_len,
|
|
|
|
|
}))
|
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
|
|
self.tcx.dcx().emit_err(FieldIsPrivate {
|
|
|
|
|
span,
|
|
|
|
|
struct_span: if self
|
|
|
|
|
.tcx
|
|
|
|
|
.sess
|
|
|
|
|
.source_map()
|
|
|
|
|
.is_multiline(fields[0].1.between(struct_span))
|
|
|
|
|
{
|
|
|
|
|
Some(struct_span)
|
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
},
|
2025-01-31 20:36:44 +00:00
|
|
|
field_names,
|
2025-01-18 20:07:05 +00:00
|
|
|
variant_descr: def.variant_descr(),
|
|
|
|
|
def_path_str: self.tcx.def_path_str(def.did()),
|
|
|
|
|
labels,
|
|
|
|
|
len: fields.len(),
|
|
|
|
|
});
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
2024-08-24 17:22:48 +00:00
|
|
|
|
|
|
|
|
fn check_expanded_fields(
|
|
|
|
|
&mut self,
|
|
|
|
|
adt: ty::AdtDef<'tcx>,
|
|
|
|
|
variant: &'tcx ty::VariantDef,
|
|
|
|
|
fields: &[hir::ExprField<'tcx>],
|
|
|
|
|
hir_id: hir::HirId,
|
|
|
|
|
span: Span,
|
2025-01-18 01:56:22 +00:00
|
|
|
struct_span: Span,
|
2024-08-24 17:22:48 +00:00
|
|
|
) {
|
2025-01-18 20:07:05 +00:00
|
|
|
let mut failed_fields = vec![];
|
2024-08-24 17:22:48 +00:00
|
|
|
for (vf_index, variant_field) in variant.fields.iter_enumerated() {
|
|
|
|
|
let field =
|
|
|
|
|
fields.iter().find(|f| self.typeck_results().field_index(f.hir_id) == vf_index);
|
|
|
|
|
let (hir_id, use_ctxt, span) = match field {
|
|
|
|
|
Some(field) => (field.hir_id, field.ident.span, field.span),
|
|
|
|
|
None => (hir_id, span, span),
|
|
|
|
|
};
|
2025-01-18 20:07:05 +00:00
|
|
|
if self.check_field(hir_id, use_ctxt, adt, variant_field) {
|
|
|
|
|
let name = match field {
|
|
|
|
|
Some(field) => field.ident.name,
|
|
|
|
|
None => variant_field.name,
|
|
|
|
|
};
|
|
|
|
|
failed_fields.push((name, span, field.is_some()));
|
|
|
|
|
}
|
2024-08-24 17:22:48 +00:00
|
|
|
}
|
2025-01-18 20:07:05 +00:00
|
|
|
self.emit_unreachable_field_error(failed_fields, adt, Some(span), struct_span);
|
2024-08-24 17:22:48 +00:00
|
|
|
}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
|
2020-06-25 22:23:41 +03:00
|
|
|
impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
|
2024-01-25 13:25:29 +03:00
|
|
|
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
|
2024-06-17 10:06:13 +00:00
|
|
|
let new_typeck_results = self.tcx.typeck_body(body_id);
|
|
|
|
|
// Do not try reporting privacy violations if we failed to infer types.
|
|
|
|
|
if new_typeck_results.tainted_by_errors.is_some() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let old_maybe_typeck_results = self.maybe_typeck_results.replace(new_typeck_results);
|
2025-02-03 10:45:49 +11:00
|
|
|
self.visit_body(self.tcx.hir_body(body_id));
|
2020-07-17 08:47:04 +00:00
|
|
|
self.maybe_typeck_results = old_maybe_typeck_results;
|
2017-01-06 21:54:24 +02:00
|
|
|
}
|
|
|
|
|
|
2019-11-30 15:08:22 +01:00
|
|
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
2021-09-30 19:38:50 +02:00
|
|
|
if let hir::ExprKind::Struct(qpath, fields, ref base) = expr.kind {
|
2020-07-17 08:47:04 +00:00
|
|
|
let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
|
2024-02-27 15:02:54 +11:00
|
|
|
let adt = self.typeck_results().expr_ty(expr).ty_adt_def().unwrap();
|
2020-03-22 13:36:56 +01:00
|
|
|
let variant = adt.variant_of_res(res);
|
2024-08-24 17:22:48 +00:00
|
|
|
match *base {
|
|
|
|
|
hir::StructTailExpr::Base(base) => {
|
|
|
|
|
// If the expression uses FRU we need to make sure all the unmentioned fields
|
|
|
|
|
// are checked for privacy (RFC 736). Rather than computing the set of
|
|
|
|
|
// unmentioned fields, just check them all.
|
2025-01-18 01:56:22 +00:00
|
|
|
self.check_expanded_fields(
|
|
|
|
|
adt,
|
|
|
|
|
variant,
|
|
|
|
|
fields,
|
|
|
|
|
base.hir_id,
|
|
|
|
|
base.span,
|
|
|
|
|
qpath.span(),
|
|
|
|
|
);
|
2020-03-22 13:36:56 +01:00
|
|
|
}
|
2024-08-24 17:22:48 +00:00
|
|
|
hir::StructTailExpr::DefaultFields(span) => {
|
2025-01-18 01:56:22 +00:00
|
|
|
self.check_expanded_fields(
|
|
|
|
|
adt,
|
|
|
|
|
variant,
|
|
|
|
|
fields,
|
|
|
|
|
expr.hir_id,
|
|
|
|
|
span,
|
|
|
|
|
qpath.span(),
|
|
|
|
|
);
|
2024-08-24 17:22:48 +00:00
|
|
|
}
|
|
|
|
|
hir::StructTailExpr::None => {
|
2025-01-18 20:07:05 +00:00
|
|
|
let mut failed_fields = vec![];
|
2024-08-24 17:22:48 +00:00
|
|
|
for field in fields {
|
2025-01-18 20:07:05 +00:00
|
|
|
let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
|
2024-08-24 17:22:48 +00:00
|
|
|
let index = self.typeck_results().field_index(field.hir_id);
|
2025-01-18 20:07:05 +00:00
|
|
|
if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
|
|
|
|
|
failed_fields.push((field.ident.name, field.ident.span, true));
|
|
|
|
|
}
|
2024-08-24 17:22:48 +00:00
|
|
|
}
|
2025-01-18 20:07:05 +00:00
|
|
|
self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-17 18:56:13 -05:00
|
|
|
intravisit::walk_expr(self, expr);
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
|
2019-11-30 15:08:22 +01:00
|
|
|
fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) {
|
2020-03-22 13:36:56 +01:00
|
|
|
if let PatKind::Struct(ref qpath, fields, _) = pat.kind {
|
2020-07-17 08:47:04 +00:00
|
|
|
let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
|
|
|
|
|
let adt = self.typeck_results().pat_ty(pat).ty_adt_def().unwrap();
|
2020-03-22 13:36:56 +01:00
|
|
|
let variant = adt.variant_of_res(res);
|
2025-01-18 20:07:05 +00:00
|
|
|
let mut failed_fields = vec![];
|
2020-03-22 13:36:56 +01:00
|
|
|
for field in fields {
|
2025-01-18 20:07:05 +00:00
|
|
|
let (hir_id, use_ctxt) = (field.hir_id, field.ident.span);
|
2022-12-04 17:59:21 +00:00
|
|
|
let index = self.typeck_results().field_index(field.hir_id);
|
2025-01-18 20:07:05 +00:00
|
|
|
if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) {
|
|
|
|
|
failed_fields.push((field.ident.name, field.ident.span, true));
|
|
|
|
|
}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
2025-01-18 20:07:05 +00:00
|
|
|
self.emit_unreachable_field_error(failed_fields, adt, None, qpath.span());
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
|
2017-04-16 21:19:24 +03:00
|
|
|
intravisit::walk_pat(self, pat);
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-22 22:46:34 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// Type privacy visitor, checks types for privacy and reports violations.
|
2021-04-19 15:57:08 +03:00
|
|
|
/// Both explicitly written types and inferred types of expressions and patterns are checked.
|
2017-04-22 22:46:34 +03:00
|
|
|
/// Checks are performed on "semantic" types regardless of names and their hygiene.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2020-06-25 22:23:41 +03:00
|
|
|
struct TypePrivacyVisitor<'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2024-01-24 00:07:00 +03:00
|
|
|
module_def_id: LocalModDefId,
|
2020-07-17 08:47:04 +00:00
|
|
|
maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>,
|
2017-04-22 22:46:34 +03:00
|
|
|
span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-25 22:23:41 +03:00
|
|
|
impl<'tcx> TypePrivacyVisitor<'tcx> {
|
2017-04-22 22:46:34 +03:00
|
|
|
fn item_is_accessible(&self, did: DefId) -> bool {
|
2024-01-24 00:07:00 +03:00
|
|
|
self.tcx.visibility(did).is_accessible_from(self.module_def_id, self.tcx)
|
2017-04-22 22:46:34 +03:00
|
|
|
}
|
|
|
|
|
|
2018-11-27 02:59:49 +00:00
|
|
|
// Take node-id of an expression or pattern and check its type for privacy.
|
2017-08-07 14:43:43 +02:00
|
|
|
fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool {
|
2017-06-03 17:51:32 +03:00
|
|
|
self.span = span;
|
2024-01-24 00:07:00 +03:00
|
|
|
let typeck_results = self
|
|
|
|
|
.maybe_typeck_results
|
|
|
|
|
.unwrap_or_else(|| span_bug!(span, "`hir::Expr` or `hir::Pat` outside of a body"));
|
2020-10-25 11:50:56 +01:00
|
|
|
let result: ControlFlow<()> = try {
|
2020-10-21 14:26:34 +02:00
|
|
|
self.visit(typeck_results.node_type(id))?;
|
2023-07-11 22:35:29 +01:00
|
|
|
self.visit(typeck_results.node_args(id))?;
|
2020-10-21 14:26:34 +02:00
|
|
|
if let Some(adjustments) = typeck_results.adjustments().get(id) {
|
|
|
|
|
adjustments.iter().try_for_each(|adjustment| self.visit(adjustment.target))?;
|
2017-06-03 17:51:32 +03:00
|
|
|
}
|
2020-10-21 14:26:34 +02:00
|
|
|
};
|
2020-10-22 10:20:24 +02:00
|
|
|
result.is_break()
|
2017-04-22 22:46:34 +03:00
|
|
|
}
|
2017-11-18 18:49:37 +03:00
|
|
|
|
2018-12-16 16:18:45 +03:00
|
|
|
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
|
|
|
|
|
let is_error = !self.item_is_accessible(def_id);
|
|
|
|
|
if is_error {
|
2023-12-18 22:21:37 +11:00
|
|
|
self.tcx.dcx().emit_err(ItemIsPrivate { span: self.span, kind, descr: descr.into() });
|
2017-11-18 18:49:37 +03:00
|
|
|
}
|
2018-12-16 16:18:45 +03:00
|
|
|
is_error
|
2017-11-18 18:49:37 +03:00
|
|
|
}
|
2017-04-22 22:46:34 +03:00
|
|
|
}
|
|
|
|
|
|
2023-07-18 07:22:46 +00:00
|
|
|
impl<'tcx> rustc_ty_utils::sig_types::SpannedTypeVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
2024-02-24 19:25:04 -05:00
|
|
|
type Result = ControlFlow<()>;
|
|
|
|
|
fn visit(&mut self, span: Span, value: impl TypeVisitable<TyCtxt<'tcx>>) -> Self::Result {
|
2023-07-18 07:22:46 +00:00
|
|
|
self.span = span;
|
|
|
|
|
value.visit_with(&mut self.skeleton())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-25 22:23:41 +03:00
|
|
|
impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
2024-01-24 00:07:00 +03:00
|
|
|
fn visit_nested_body(&mut self, body_id: hir::BodyId) {
|
2020-07-17 08:47:04 +00:00
|
|
|
let old_maybe_typeck_results =
|
2024-01-24 00:07:00 +03:00
|
|
|
self.maybe_typeck_results.replace(self.tcx.typeck_body(body_id));
|
2025-02-03 10:45:49 +11:00
|
|
|
self.visit_body(self.tcx.hir_body(body_id));
|
2020-07-17 08:47:04 +00:00
|
|
|
self.maybe_typeck_results = old_maybe_typeck_results;
|
2017-04-22 22:46:34 +03:00
|
|
|
}
|
|
|
|
|
|
2025-01-11 19:12:36 +00:00
|
|
|
fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx, AmbigArg>) {
|
2017-09-16 16:45:49 +03:00
|
|
|
self.span = hir_ty.span;
|
2023-07-18 07:22:46 +00:00
|
|
|
if self
|
|
|
|
|
.visit(
|
|
|
|
|
self.maybe_typeck_results
|
|
|
|
|
.unwrap_or_else(|| span_bug!(hir_ty.span, "`hir::Ty` outside of a body"))
|
|
|
|
|
.node_type(hir_ty.hir_id),
|
|
|
|
|
)
|
|
|
|
|
.is_break()
|
|
|
|
|
{
|
|
|
|
|
return;
|
2017-09-16 16:45:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intravisit::walk_ty(self, hir_ty);
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-11 19:12:36 +00:00
|
|
|
fn visit_infer(
|
|
|
|
|
&mut self,
|
|
|
|
|
inf_id: rustc_hir::HirId,
|
|
|
|
|
inf_span: Span,
|
|
|
|
|
_kind: InferKind<'tcx>,
|
|
|
|
|
) -> Self::Result {
|
|
|
|
|
self.span = inf_span;
|
2023-07-18 07:22:46 +00:00
|
|
|
if let Some(ty) = self
|
|
|
|
|
.maybe_typeck_results
|
2025-01-11 19:12:36 +00:00
|
|
|
.unwrap_or_else(|| span_bug!(inf_span, "Inference variable outside of a body"))
|
|
|
|
|
.node_type_opt(inf_id)
|
2023-07-18 07:22:46 +00:00
|
|
|
{
|
|
|
|
|
if self.visit(ty).is_break() {
|
|
|
|
|
return;
|
2021-04-26 18:19:23 +00:00
|
|
|
}
|
|
|
|
|
} else {
|
2023-07-18 07:22:46 +00:00
|
|
|
// FIXME: check types of const infers here.
|
2021-04-26 18:19:23 +00:00
|
|
|
}
|
2025-01-11 19:12:36 +00:00
|
|
|
|
|
|
|
|
self.visit_id(inf_id)
|
2021-04-26 18:19:23 +00:00
|
|
|
}
|
|
|
|
|
|
2017-04-22 22:46:34 +03:00
|
|
|
// Check types of expressions
|
2019-11-30 15:08:22 +01:00
|
|
|
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
|
2017-08-07 14:43:43 +02:00
|
|
|
if self.check_expr_pat_type(expr.hir_id, expr.span) {
|
2017-04-22 22:46:34 +03:00
|
|
|
// Do not check nested expressions if the error already happened.
|
|
|
|
|
return;
|
|
|
|
|
}
|
2019-09-26 14:39:48 +01:00
|
|
|
match expr.kind {
|
2021-09-30 19:38:50 +02:00
|
|
|
hir::ExprKind::Assign(_, rhs, _) | hir::ExprKind::Match(rhs, ..) => {
|
2017-04-22 22:46:34 +03:00
|
|
|
// Do not report duplicate errors for `x = y` and `match x { ... }`.
|
2017-08-07 14:43:43 +02:00
|
|
|
if self.check_expr_pat_type(rhs.hir_id, rhs.span) {
|
2017-04-22 22:46:34 +03:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-12-01 11:17:50 -06:00
|
|
|
hir::ExprKind::MethodCall(segment, ..) => {
|
2017-04-22 22:46:34 +03:00
|
|
|
// Method calls have to be checked specially.
|
2021-12-01 11:17:50 -06:00
|
|
|
self.span = segment.ident.span;
|
2024-01-24 00:07:00 +03:00
|
|
|
let typeck_results = self
|
|
|
|
|
.maybe_typeck_results
|
|
|
|
|
.unwrap_or_else(|| span_bug!(self.span, "`hir::Expr` outside of a body"));
|
|
|
|
|
if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
|
2023-07-11 22:35:29 +01:00
|
|
|
if self.visit(self.tcx.type_of(def_id).instantiate_identity()).is_break() {
|
2018-06-28 22:49:01 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
self.tcx
|
2023-12-18 22:21:37 +11:00
|
|
|
.dcx()
|
2023-11-30 15:01:11 +11:00
|
|
|
.span_delayed_bug(expr.span, "no type-dependent def for method call");
|
2017-04-22 22:46:34 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intravisit::walk_expr(self, expr);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-18 18:49:37 +03:00
|
|
|
// Prohibit access to associated items with insufficient nominal visibility.
|
2017-11-18 19:15:16 +03:00
|
|
|
//
|
|
|
|
|
// Additionally, until better reachability analysis for macros 2.0 is available,
|
|
|
|
|
// we prohibit access to private statics from other crates, this allows to give
|
|
|
|
|
// more code internal visibility at link time. (Access to private functions
|
2018-02-16 15:56:50 +01:00
|
|
|
// is already prohibited by type privacy for function types.)
|
2019-12-01 16:08:58 +01:00
|
|
|
fn visit_qpath(&mut self, qpath: &'tcx hir::QPath<'tcx>, id: hir::HirId, span: Span) {
|
2020-06-25 22:23:41 +03:00
|
|
|
let def = match qpath {
|
|
|
|
|
hir::QPath::Resolved(_, path) => match path.res {
|
|
|
|
|
Res::Def(kind, def_id) => Some((kind, def_id)),
|
|
|
|
|
_ => None,
|
|
|
|
|
},
|
2024-01-24 00:07:00 +03:00
|
|
|
hir::QPath::TypeRelative(..) | hir::QPath::LangItem(..) => {
|
|
|
|
|
match self.maybe_typeck_results {
|
|
|
|
|
Some(typeck_results) => typeck_results.type_dependent_def(id),
|
|
|
|
|
// FIXME: Check type-relative associated types in signatures.
|
|
|
|
|
None => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
2017-11-18 18:49:37 +03:00
|
|
|
};
|
2020-10-26 20:02:06 -04:00
|
|
|
let def = def.filter(|(kind, _)| {
|
|
|
|
|
matches!(
|
|
|
|
|
kind,
|
2024-02-23 23:12:20 +00:00
|
|
|
DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::Static { .. }
|
2020-10-26 20:02:06 -04:00
|
|
|
)
|
2019-04-20 19:46:19 +03:00
|
|
|
});
|
|
|
|
|
if let Some((kind, def_id)) = def {
|
|
|
|
|
let is_local_static =
|
2024-02-23 23:12:20 +00:00
|
|
|
if let DefKind::Static { .. } = kind { def_id.is_local() } else { false };
|
2017-11-18 19:15:16 +03:00
|
|
|
if !self.item_is_accessible(def_id) && !is_local_static {
|
2022-12-09 15:56:23 +00:00
|
|
|
let name = match *qpath {
|
|
|
|
|
hir::QPath::LangItem(it, ..) => {
|
|
|
|
|
self.tcx.lang_items().get(it).map(|did| self.tcx.def_path_str(did))
|
2020-08-04 14:34:24 +01:00
|
|
|
}
|
2022-12-09 15:56:23 +00:00
|
|
|
hir::QPath::Resolved(_, path) => Some(self.tcx.def_path_str(path.res.def_id())),
|
2020-03-23 11:32:07 +01:00
|
|
|
hir::QPath::TypeRelative(_, segment) => Some(segment.ident.to_string()),
|
2017-11-18 18:49:37 +03:00
|
|
|
};
|
2023-02-21 14:05:32 -07:00
|
|
|
let kind = self.tcx.def_descr(def_id);
|
2022-12-09 15:56:23 +00:00
|
|
|
let sess = self.tcx.sess;
|
2022-06-22 13:42:30 +01:00
|
|
|
let _ = match name {
|
2022-07-29 06:48:39 +00:00
|
|
|
Some(name) => {
|
2023-12-18 22:21:37 +11:00
|
|
|
sess.dcx().emit_err(ItemIsPrivate { span, kind, descr: (&name).into() })
|
2022-07-29 06:48:39 +00:00
|
|
|
}
|
2023-12-18 22:21:37 +11:00
|
|
|
None => sess.dcx().emit_err(UnnamedItemIsPrivate { span, kind }),
|
2020-03-23 11:32:07 +01:00
|
|
|
};
|
2017-11-18 18:49:37 +03:00
|
|
|
return;
|
2017-06-03 17:51:32 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-12 10:43:34 +10:00
|
|
|
intravisit::walk_qpath(self, qpath, id);
|
2017-06-03 17:51:32 +03:00
|
|
|
}
|
|
|
|
|
|
2018-11-27 02:59:49 +00:00
|
|
|
// Check types of patterns.
|
2019-11-30 15:08:22 +01:00
|
|
|
fn visit_pat(&mut self, pattern: &'tcx hir::Pat<'tcx>) {
|
2017-08-07 14:43:43 +02:00
|
|
|
if self.check_expr_pat_type(pattern.hir_id, pattern.span) {
|
2017-04-22 22:46:34 +03:00
|
|
|
// Do not check nested patterns if the error already happened.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intravisit::walk_pat(self, pattern);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-20 17:50:31 +01:00
|
|
|
fn visit_local(&mut self, local: &'tcx hir::LetStmt<'tcx>) {
|
2021-09-30 19:38:50 +02:00
|
|
|
if let Some(init) = local.init {
|
2017-08-07 14:43:43 +02:00
|
|
|
if self.check_expr_pat_type(init.hir_id, init.span) {
|
2017-04-22 22:46:34 +03:00
|
|
|
// Do not report duplicate errors for `let x = y`.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
intravisit::walk_local(self, local);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-14 12:38:06 -05:00
|
|
|
impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
|
2024-02-24 17:22:28 -05:00
|
|
|
type Result = ControlFlow<()>;
|
2019-06-14 00:48:52 +03:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
|
|
|
|
self.tcx
|
|
|
|
|
}
|
2020-10-21 14:26:34 +02:00
|
|
|
fn visit_def_id(
|
|
|
|
|
&mut self,
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
kind: &str,
|
|
|
|
|
descr: &dyn fmt::Display,
|
2024-02-24 17:22:28 -05:00
|
|
|
) -> Self::Result {
|
2020-10-21 14:26:34 +02:00
|
|
|
if self.check_def_id(def_id, kind, descr) {
|
2023-01-17 23:17:13 -08:00
|
|
|
ControlFlow::Break(())
|
2020-10-21 14:26:34 +02:00
|
|
|
} else {
|
2023-01-17 23:17:13 -08:00
|
|
|
ControlFlow::Continue(())
|
2020-10-21 14:26:34 +02:00
|
|
|
}
|
2017-04-22 22:46:34 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-21 17:38:17 +03:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
/// SearchInterfaceForPrivateItemsVisitor traverses an item's interface and
|
|
|
|
|
/// finds any private components in it.
|
|
|
|
|
/// PrivateItemsInPublicInterfacesVisitor ensures there are no private types
|
|
|
|
|
/// and traits in public interfaces.
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2019-06-11 22:03:44 +03:00
|
|
|
struct SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2021-08-14 20:51:49 +03:00
|
|
|
item_def_id: LocalDefId,
|
2018-11-27 02:59:49 +00:00
|
|
|
/// The visitor checks that each component type is at least this visible.
|
2016-04-01 20:16:31 +00:00
|
|
|
required_visibility: ty::Visibility,
|
2023-05-18 14:57:45 +03:00
|
|
|
required_effective_vis: Option<EffectiveVisibility>,
|
2017-11-18 20:32:24 +03:00
|
|
|
in_assoc_ty: bool,
|
2023-05-18 14:57:45 +03:00
|
|
|
in_primary_interface: bool,
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 12:38:06 -05:00
|
|
|
impl SearchInterfaceForPrivateItemsVisitor<'_> {
|
2016-11-12 12:24:17 +02:00
|
|
|
fn generics(&mut self) -> &mut Self {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.in_primary_interface = true;
|
2024-05-09 20:56:44 -04:00
|
|
|
for param in &self.tcx.generics_of(self.item_def_id).own_params {
|
2018-04-19 00:40:22 +01:00
|
|
|
match param.kind {
|
2019-02-20 01:20:06 +00:00
|
|
|
GenericParamDefKind::Lifetime => {}
|
2018-05-16 13:03:04 +03:00
|
|
|
GenericParamDefKind::Type { has_default, .. } => {
|
|
|
|
|
if has_default {
|
2025-02-22 23:55:08 +00:00
|
|
|
let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
|
2018-04-13 23:12:14 +01:00
|
|
|
}
|
|
|
|
|
}
|
2021-08-25 10:21:39 +01:00
|
|
|
// FIXME(generic_const_exprs): May want to look inside const here
|
2020-08-11 00:02:45 +00:00
|
|
|
GenericParamDefKind::Const { .. } => {
|
2025-02-22 23:55:08 +00:00
|
|
|
let _ = self.visit(self.tcx.type_of(param.def_id).instantiate_identity());
|
2019-02-20 01:20:06 +00:00
|
|
|
}
|
2017-01-25 22:01:11 +02:00
|
|
|
}
|
|
|
|
|
}
|
2016-11-12 12:24:17 +02:00
|
|
|
self
|
2016-04-01 20:16:31 +00:00
|
|
|
}
|
|
|
|
|
|
2016-11-12 12:24:17 +02:00
|
|
|
fn predicates(&mut self) -> &mut Self {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.in_primary_interface = false;
|
2018-11-27 02:59:49 +00:00
|
|
|
// N.B., we use `explicit_predicates_of` and not `predicates_of`
|
2018-08-28 00:46:08 -04:00
|
|
|
// because we don't want to report privacy errors due to where
|
|
|
|
|
// clauses that the compiler inferred. We only want to
|
|
|
|
|
// consider the ones that the user wrote. This is important
|
|
|
|
|
// for the inferred outlives rules; see
|
2023-01-05 09:45:44 +01:00
|
|
|
// `tests/ui/rfc-2093-infer-outlives/privacy.rs`.
|
2025-02-22 23:55:08 +00:00
|
|
|
let _ = self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id));
|
2016-11-12 12:24:17 +02:00
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-27 21:36:35 +01:00
|
|
|
fn bounds(&mut self) -> &mut Self {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.in_primary_interface = false;
|
2025-02-22 23:55:08 +00:00
|
|
|
let _ = self.visit_clauses(self.tcx.explicit_item_bounds(self.item_def_id).skip_binder());
|
2020-06-27 21:36:35 +01:00
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-24 15:20:46 +03:00
|
|
|
fn ty(&mut self) -> &mut Self {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.in_primary_interface = true;
|
2025-02-22 23:55:08 +00:00
|
|
|
let _ = self.visit(self.tcx.type_of(self.item_def_id).instantiate_identity());
|
2016-11-12 12:24:17 +02:00
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-16 16:18:45 +03:00
|
|
|
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
|
2019-01-13 18:07:42 -05:00
|
|
|
if self.leaks_private_dep(def_id) {
|
2024-01-16 16:27:02 +11:00
|
|
|
self.tcx.emit_node_span_lint(
|
2019-02-26 11:48:34 +01:00
|
|
|
lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
|
2023-11-24 19:28:19 +03:00
|
|
|
self.tcx.local_def_id_to_hir_id(self.item_def_id),
|
2021-08-14 20:51:49 +03:00
|
|
|
self.tcx.def_span(self.item_def_id.to_def_id()),
|
2022-07-11 16:29:24 +01:00
|
|
|
FromPrivateDependencyInPublicInterface {
|
|
|
|
|
kind,
|
2022-08-05 16:43:52 +00:00
|
|
|
descr: descr.into(),
|
2022-07-11 16:29:24 +01:00
|
|
|
krate: self.tcx.crate_name(def_id.krate),
|
2020-01-31 22:24:57 +10:00
|
|
|
},
|
2019-02-26 11:48:34 +01:00
|
|
|
);
|
2019-01-13 18:07:42 -05:00
|
|
|
}
|
|
|
|
|
|
2022-08-28 00:10:06 +03:00
|
|
|
let Some(local_def_id) = def_id.as_local() else {
|
|
|
|
|
return false;
|
2018-12-16 16:18:45 +03:00
|
|
|
};
|
2017-07-11 10:33:09 -04:00
|
|
|
|
2022-08-28 00:10:06 +03:00
|
|
|
let vis = self.tcx.local_visibility(local_def_id);
|
2023-05-18 14:57:45 +03:00
|
|
|
let span = self.tcx.def_span(self.item_def_id.to_def_id());
|
|
|
|
|
let vis_span = self.tcx.def_span(def_id);
|
2023-06-19 17:06:00 +03:00
|
|
|
if self.in_assoc_ty && !vis.is_at_least(self.required_visibility, self.tcx) {
|
2020-10-17 02:28:11 +03:00
|
|
|
let vis_descr = match vis {
|
|
|
|
|
ty::Visibility::Public => "public",
|
|
|
|
|
ty::Visibility::Restricted(vis_def_id) => {
|
2023-09-07 06:27:10 +00:00
|
|
|
if vis_def_id
|
|
|
|
|
== self.tcx.parent_module_from_def_id(local_def_id).to_local_def_id()
|
|
|
|
|
{
|
2020-10-17 02:28:11 +03:00
|
|
|
"private"
|
|
|
|
|
} else if vis_def_id.is_top_level_module() {
|
|
|
|
|
"crate-private"
|
|
|
|
|
} else {
|
|
|
|
|
"restricted"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2023-05-18 14:57:45 +03:00
|
|
|
|
2023-12-18 22:21:37 +11:00
|
|
|
self.tcx.dcx().emit_err(InPublicInterface {
|
2023-06-19 17:06:00 +03:00
|
|
|
span,
|
|
|
|
|
vis_descr,
|
|
|
|
|
kind,
|
|
|
|
|
descr: descr.into(),
|
|
|
|
|
vis_span,
|
|
|
|
|
});
|
|
|
|
|
return false;
|
2017-07-11 10:33:09 -04:00
|
|
|
}
|
2018-12-15 08:01:57 -05:00
|
|
|
|
2023-05-18 14:57:45 +03:00
|
|
|
let Some(effective_vis) = self.required_effective_vis else {
|
|
|
|
|
return false;
|
|
|
|
|
};
|
|
|
|
|
|
2023-06-15 19:07:51 +03:00
|
|
|
let reachable_at_vis = *effective_vis.at_level(Level::Reachable);
|
2023-05-18 14:57:45 +03:00
|
|
|
|
2023-06-15 19:07:51 +03:00
|
|
|
if !vis.is_at_least(reachable_at_vis, self.tcx) {
|
2023-05-18 14:57:45 +03:00
|
|
|
let lint = if self.in_primary_interface {
|
|
|
|
|
lint::builtin::PRIVATE_INTERFACES
|
|
|
|
|
} else {
|
|
|
|
|
lint::builtin::PRIVATE_BOUNDS
|
|
|
|
|
};
|
2024-01-16 16:27:02 +11:00
|
|
|
self.tcx.emit_node_span_lint(
|
2023-05-18 14:57:45 +03:00
|
|
|
lint,
|
2023-11-24 19:28:19 +03:00
|
|
|
self.tcx.local_def_id_to_hir_id(self.item_def_id),
|
2023-06-29 16:24:07 +03:00
|
|
|
span,
|
2023-05-18 14:57:45 +03:00
|
|
|
PrivateInterfacesOrBoundsLint {
|
|
|
|
|
item_span: span,
|
|
|
|
|
item_kind: self.tcx.def_descr(self.item_def_id.to_def_id()),
|
|
|
|
|
item_descr: (&LazyDefPathStr {
|
|
|
|
|
def_id: self.item_def_id.to_def_id(),
|
|
|
|
|
tcx: self.tcx,
|
|
|
|
|
})
|
|
|
|
|
.into(),
|
2023-12-01 10:25:40 +08:00
|
|
|
item_vis_descr: &reachable_at_vis.to_string(self.item_def_id, self.tcx),
|
2023-05-18 14:57:45 +03:00
|
|
|
ty_span: vis_span,
|
|
|
|
|
ty_kind: kind,
|
|
|
|
|
ty_descr: descr.into(),
|
2023-12-01 10:25:40 +08:00
|
|
|
ty_vis_descr: &vis.to_string(local_def_id, self.tcx),
|
2023-05-18 14:57:45 +03:00
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-16 16:18:45 +03:00
|
|
|
false
|
2017-07-11 10:33:09 -04:00
|
|
|
}
|
2018-12-15 07:00:15 -05:00
|
|
|
|
|
|
|
|
/// An item is 'leaked' from a private dependency if all
|
|
|
|
|
/// of the following are true:
|
|
|
|
|
/// 1. It's contained within a public type
|
2019-01-30 16:00:40 -05:00
|
|
|
/// 2. It comes from a private crate
|
2018-12-15 07:00:15 -05:00
|
|
|
fn leaks_private_dep(&self, item_id: DefId) -> bool {
|
2021-11-07 19:53:26 -08:00
|
|
|
let ret = self.required_visibility.is_public() && self.tcx.is_private_dep(item_id.krate);
|
2018-12-15 08:01:57 -05:00
|
|
|
|
2022-08-31 13:09:26 +00:00
|
|
|
debug!("leaks_private_dep(item_id={:?})={}", item_id, ret);
|
2020-03-20 15:03:11 +01:00
|
|
|
ret
|
2017-07-11 10:33:09 -04:00
|
|
|
}
|
2015-11-27 01:48:26 +03:00
|
|
|
}
|
|
|
|
|
|
2021-12-14 12:38:06 -05:00
|
|
|
impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
2024-02-24 17:22:28 -05:00
|
|
|
type Result = ControlFlow<()>;
|
2019-06-14 00:48:52 +03:00
|
|
|
fn tcx(&self) -> TyCtxt<'tcx> {
|
|
|
|
|
self.tcx
|
|
|
|
|
}
|
2020-10-21 14:26:34 +02:00
|
|
|
fn visit_def_id(
|
|
|
|
|
&mut self,
|
|
|
|
|
def_id: DefId,
|
|
|
|
|
kind: &str,
|
|
|
|
|
descr: &dyn fmt::Display,
|
2024-02-24 17:22:28 -05:00
|
|
|
) -> Self::Result {
|
2020-10-21 14:26:34 +02:00
|
|
|
if self.check_def_id(def_id, kind, descr) {
|
2023-01-17 23:17:13 -08:00
|
|
|
ControlFlow::Break(())
|
2020-10-21 14:26:34 +02:00
|
|
|
} else {
|
2023-01-17 23:17:13 -08:00
|
|
|
ControlFlow::Continue(())
|
2020-10-21 14:26:34 +02:00
|
|
|
}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-12 09:25:11 +10:00
|
|
|
struct PrivateItemsInPublicInterfacesChecker<'a, 'tcx> {
|
2019-06-14 00:48:52 +03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-05-18 14:57:45 +03:00
|
|
|
effective_visibilities: &'a EffectiveVisibilities,
|
2015-11-21 17:38:17 +03:00
|
|
|
}
|
|
|
|
|
|
2024-09-12 09:25:11 +10:00
|
|
|
impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
|
2019-06-12 00:11:55 +03:00
|
|
|
fn check(
|
|
|
|
|
&self,
|
2021-08-14 20:51:49 +03:00
|
|
|
def_id: LocalDefId,
|
2019-06-12 00:11:55 +03:00
|
|
|
required_visibility: ty::Visibility,
|
2023-05-18 14:57:45 +03:00
|
|
|
required_effective_vis: Option<EffectiveVisibility>,
|
2019-06-12 00:11:55 +03:00
|
|
|
) -> SearchInterfaceForPrivateItemsVisitor<'tcx> {
|
2016-11-12 12:24:17 +02:00
|
|
|
SearchInterfaceForPrivateItemsVisitor {
|
|
|
|
|
tcx: self.tcx,
|
2021-08-14 20:51:49 +03:00
|
|
|
item_def_id: def_id,
|
2017-08-06 22:54:09 -07:00
|
|
|
required_visibility,
|
2023-05-18 14:57:45 +03:00
|
|
|
required_effective_vis,
|
2017-11-18 20:32:24 +03:00
|
|
|
in_assoc_ty: false,
|
2023-05-18 14:57:45 +03:00
|
|
|
in_primary_interface: true,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn check_unnameable(&self, def_id: LocalDefId, effective_vis: Option<EffectiveVisibility>) {
|
|
|
|
|
let Some(effective_vis) = effective_vis else {
|
|
|
|
|
return;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let reexported_at_vis = effective_vis.at_level(Level::Reexported);
|
|
|
|
|
let reachable_at_vis = effective_vis.at_level(Level::Reachable);
|
|
|
|
|
|
2023-07-30 14:00:18 +03:00
|
|
|
if reachable_at_vis.is_public() && reexported_at_vis != reachable_at_vis {
|
2023-11-24 19:28:19 +03:00
|
|
|
let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
|
2023-05-18 14:57:45 +03:00
|
|
|
let span = self.tcx.def_span(def_id.to_def_id());
|
2024-01-16 16:27:02 +11:00
|
|
|
self.tcx.emit_node_span_lint(
|
2023-05-18 14:57:45 +03:00
|
|
|
lint::builtin::UNNAMEABLE_TYPES,
|
|
|
|
|
hir_id,
|
|
|
|
|
span,
|
|
|
|
|
UnnameableTypesLint {
|
|
|
|
|
span,
|
|
|
|
|
kind: self.tcx.def_descr(def_id.to_def_id()),
|
|
|
|
|
descr: (&LazyDefPathStr { def_id: def_id.to_def_id(), tcx: self.tcx }).into(),
|
2023-12-01 10:25:40 +08:00
|
|
|
reachable_vis: &reachable_at_vis.to_string(def_id, self.tcx),
|
|
|
|
|
reexported_vis: &reexported_at_vis.to_string(def_id, self.tcx),
|
2023-05-18 14:57:45 +03:00
|
|
|
},
|
|
|
|
|
);
|
2016-11-12 12:24:17 +02:00
|
|
|
}
|
2015-11-21 17:38:17 +03:00
|
|
|
}
|
2019-01-16 01:47:49 +03:00
|
|
|
|
2019-05-29 00:35:14 +03:00
|
|
|
fn check_assoc_item(
|
|
|
|
|
&self,
|
2021-08-14 20:51:49 +03:00
|
|
|
def_id: LocalDefId,
|
2019-05-29 00:35:14 +03:00
|
|
|
assoc_item_kind: AssocItemKind,
|
|
|
|
|
vis: ty::Visibility,
|
2023-05-18 14:57:45 +03:00
|
|
|
effective_vis: Option<EffectiveVisibility>,
|
2019-05-29 00:35:14 +03:00
|
|
|
) {
|
2023-05-18 14:57:45 +03:00
|
|
|
let mut check = self.check(def_id, vis, effective_vis);
|
2019-01-16 01:47:49 +03:00
|
|
|
|
|
|
|
|
let (check_ty, is_assoc_ty) = match assoc_item_kind {
|
2020-04-01 10:09:50 +08:00
|
|
|
AssocItemKind::Const | AssocItemKind::Fn { .. } => (true, false),
|
2023-06-01 06:14:06 +00:00
|
|
|
AssocItemKind::Type => (self.tcx.defaultness(def_id).has_value(), true),
|
2019-01-16 01:47:49 +03:00
|
|
|
};
|
2023-05-18 14:57:45 +03:00
|
|
|
|
2019-01-16 01:47:49 +03:00
|
|
|
check.in_assoc_ty = is_assoc_ty;
|
|
|
|
|
check.generics().predicates();
|
|
|
|
|
if check_ty {
|
|
|
|
|
check.ty();
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-01-07 17:25:33 +01:00
|
|
|
|
2023-05-18 14:57:45 +03:00
|
|
|
fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> {
|
|
|
|
|
self.effective_visibilities.effective_vis(def_id).copied()
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-29 16:29:14 +10:00
|
|
|
fn check_item(&mut self, id: ItemId) {
|
2016-11-12 12:24:17 +02:00
|
|
|
let tcx = self.tcx;
|
2022-10-27 14:02:18 +11:00
|
|
|
let def_id = id.owner_id.def_id;
|
2022-09-20 14:11:23 +09:00
|
|
|
let item_visibility = tcx.local_visibility(def_id);
|
2023-05-18 14:57:45 +03:00
|
|
|
let effective_vis = self.get(def_id);
|
2022-09-20 14:11:23 +09:00
|
|
|
let def_kind = tcx.def_kind(def_id);
|
2022-05-05 13:34:27 -04:00
|
|
|
|
|
|
|
|
match def_kind {
|
2024-02-23 23:12:20 +00:00
|
|
|
DefKind::Const | DefKind::Static { .. } | DefKind::Fn | DefKind::TyAlias => {
|
2023-09-26 02:15:32 +00:00
|
|
|
if let DefKind::TyAlias = def_kind {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.check_unnameable(def_id, effective_vis);
|
|
|
|
|
}
|
|
|
|
|
self.check(def_id, item_visibility, effective_vis).generics().predicates().ty();
|
2016-11-12 12:24:17 +02:00
|
|
|
}
|
2022-05-05 13:34:27 -04:00
|
|
|
DefKind::OpaqueTy => {
|
2019-08-01 00:41:54 +01:00
|
|
|
// `ty()` for opaque types is the underlying type,
|
2019-01-13 00:41:11 +03:00
|
|
|
// it's not a part of interface, so we skip it.
|
2023-05-18 14:57:45 +03:00
|
|
|
self.check(def_id, item_visibility, effective_vis).generics().bounds();
|
2019-01-13 00:41:11 +03:00
|
|
|
}
|
2022-05-05 13:34:27 -04:00
|
|
|
DefKind::Trait => {
|
2025-02-03 10:45:49 +11:00
|
|
|
let item = tcx.hir_item(id);
|
2022-05-05 13:34:27 -04:00
|
|
|
if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.check_unnameable(item.owner_id.def_id, effective_vis);
|
|
|
|
|
|
|
|
|
|
self.check(item.owner_id.def_id, item_visibility, effective_vis)
|
|
|
|
|
.generics()
|
|
|
|
|
.predicates();
|
2016-11-12 12:24:17 +02:00
|
|
|
|
2022-05-05 13:34:27 -04:00
|
|
|
for trait_item_ref in trait_item_refs {
|
|
|
|
|
self.check_assoc_item(
|
2022-10-27 14:02:18 +11:00
|
|
|
trait_item_ref.id.owner_id.def_id,
|
2022-05-05 13:34:27 -04:00
|
|
|
trait_item_ref.kind,
|
|
|
|
|
item_visibility,
|
2023-05-18 14:57:45 +03:00
|
|
|
effective_vis,
|
2022-05-05 13:34:27 -04:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
if let AssocItemKind::Type = trait_item_ref.kind {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.check(
|
|
|
|
|
trait_item_ref.id.owner_id.def_id,
|
|
|
|
|
item_visibility,
|
|
|
|
|
effective_vis,
|
|
|
|
|
)
|
|
|
|
|
.bounds();
|
2022-05-05 13:34:27 -04:00
|
|
|
}
|
2020-06-27 21:36:35 +01:00
|
|
|
}
|
2016-11-12 12:24:17 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-05-05 13:34:27 -04:00
|
|
|
DefKind::TraitAlias => {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.check(def_id, item_visibility, effective_vis).generics().predicates();
|
2017-10-02 12:28:16 +00:00
|
|
|
}
|
2022-05-05 13:34:27 -04:00
|
|
|
DefKind::Enum => {
|
2025-02-03 10:45:49 +11:00
|
|
|
let item = tcx.hir_item(id);
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
if let hir::ItemKind::Enum(_, ref def, _) = item.kind {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.check_unnameable(item.owner_id.def_id, effective_vis);
|
|
|
|
|
|
|
|
|
|
self.check(item.owner_id.def_id, item_visibility, effective_vis)
|
|
|
|
|
.generics()
|
|
|
|
|
.predicates();
|
2016-11-12 12:24:17 +02:00
|
|
|
|
2022-05-05 13:34:27 -04:00
|
|
|
for variant in def.variants {
|
|
|
|
|
for field in variant.data.fields() {
|
2023-05-18 14:57:45 +03:00
|
|
|
self.check(field.def_id, item_visibility, effective_vis).ty();
|
2022-05-05 13:34:27 -04:00
|
|
|
}
|
2016-11-12 12:24:17 +02:00
|
|
|
}
|
|
|
|
|
}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
2018-11-27 02:59:49 +00:00
|
|
|
// Subitems of foreign modules have their own publicity.
|
2022-05-05 13:34:27 -04:00
|
|
|
DefKind::ForeignMod => {
|
2025-02-03 10:45:49 +11:00
|
|
|
let item = tcx.hir_item(id);
|
2022-05-05 13:34:27 -04:00
|
|
|
if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
|
|
|
|
|
for foreign_item in items {
|
2025-02-03 10:45:49 +11:00
|
|
|
let foreign_item = tcx.hir_foreign_item(foreign_item.id);
|
2023-05-18 14:57:45 +03:00
|
|
|
|
|
|
|
|
let ev = self.get(foreign_item.owner_id.def_id);
|
|
|
|
|
let vis = tcx.local_visibility(foreign_item.owner_id.def_id);
|
|
|
|
|
|
|
|
|
|
if let ForeignItemKind::Type = foreign_item.kind {
|
|
|
|
|
self.check_unnameable(foreign_item.owner_id.def_id, ev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.check(foreign_item.owner_id.def_id, vis, ev)
|
2022-10-27 14:02:18 +11:00
|
|
|
.generics()
|
|
|
|
|
.predicates()
|
|
|
|
|
.ty();
|
2022-05-05 13:34:27 -04:00
|
|
|
}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
2015-11-21 17:38:17 +03:00
|
|
|
}
|
2018-11-27 02:59:49 +00:00
|
|
|
// Subitems of structs and unions have their own publicity.
|
2022-05-05 13:34:27 -04:00
|
|
|
DefKind::Struct | DefKind::Union => {
|
2025-02-03 10:45:49 +11:00
|
|
|
let item = tcx.hir_item(id);
|
Move `hir::Item::ident` into `hir::ItemKind`.
`hir::Item` has an `ident` field.
- It's always non-empty for these item kinds: `ExternCrate`, `Static`,
`Const`, `Fn`, `Macro`, `Mod`, `TyAlias`, `Enum`, `Struct`, `Union`,
Trait`, TraitAalis`.
- It's always empty for these item kinds: `ForeignMod`, `GlobalAsm`,
`Impl`.
- For `Use`, it is non-empty for `UseKind::Single` and empty for
`UseKind::{Glob,ListStem}`.
All of this is quite non-obvious; the only documentation is a single
comment saying "The name might be a dummy name in case of anonymous
items". Some sites that handle items check for an empty ident, some
don't. This is a very C-like way of doing things, but this is Rust, we
have sum types, we can do this properly and never forget to check for
the exceptional case and never YOLO possibly empty identifiers (or
possibly dummy spans) around and hope that things will work out.
The commit is large but it's mostly obvious plumbing work. Some notable
things.
- A similar transformation makes sense for `ast::Item`, but this is
already a big change. That can be done later.
- Lots of assertions are added to item lowering to ensure that
identifiers are empty/non-empty as expected. These will be removable
when `ast::Item` is done later.
- `ItemKind::Use` doesn't get an `Ident`, but `UseKind::Single` does.
- `lower_use_tree` is significantly simpler. No more confusing `&mut
Ident` to deal with.
- `ItemKind::ident` is a new method, it returns an `Option<Ident>`. It's
used with `unwrap` in a few places; sometimes it's hard to tell
exactly which item kinds might occur. None of these unwraps fail on
the test suite. It's conceivable that some might fail on alternative
input. We can deal with those if/when they happen.
- In `trait_path` the `find_map`/`if let` is replaced with a loop, and
things end up much clearer that way.
- `named_span` no longer checks for an empty name; instead the call site
now checks for a missing identifier if necessary.
- `maybe_inline_local` doesn't need the `glob` argument, it can be
computed in-function from the `renamed` argument.
- `arbitrary_source_item_ordering::check_mod` had a big `if` statement
that was just getting the ident from the item kinds that had one. It
could be mostly replaced by a single call to the new `ItemKind::ident`
method.
- `ItemKind` grows from 56 to 64 bytes, but `Item` stays the same size,
and that's what matters, because `ItemKind` only occurs within `Item`.
2025-03-06 19:07:36 +11:00
|
|
|
if let hir::ItemKind::Struct(_, ref struct_def, _)
|
|
|
|
|
| hir::ItemKind::Union(_, ref struct_def, _) = item.kind
|
2022-05-05 13:34:27 -04:00
|
|
|
{
|
2023-05-18 14:57:45 +03:00
|
|
|
self.check_unnameable(item.owner_id.def_id, effective_vis);
|
|
|
|
|
self.check(item.owner_id.def_id, item_visibility, effective_vis)
|
|
|
|
|
.generics()
|
|
|
|
|
.predicates();
|
2016-04-01 20:16:31 +00:00
|
|
|
|
2022-05-05 13:34:27 -04:00
|
|
|
for field in struct_def.fields() {
|
2022-11-06 19:46:55 +00:00
|
|
|
let field_visibility = tcx.local_visibility(field.def_id);
|
2023-05-18 14:57:45 +03:00
|
|
|
let field_ev = self.get(field.def_id);
|
|
|
|
|
|
|
|
|
|
self.check(
|
|
|
|
|
field.def_id,
|
|
|
|
|
min(item_visibility, field_visibility, tcx),
|
|
|
|
|
field_ev,
|
|
|
|
|
)
|
|
|
|
|
.ty();
|
2022-05-05 13:34:27 -04:00
|
|
|
}
|
2015-11-21 17:38:17 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// An inherent impl is public when its type is public
|
2018-11-27 02:59:49 +00:00
|
|
|
// Subitems of inherent impls have their own publicity.
|
2015-11-21 17:38:17 +03:00
|
|
|
// A trait impl is public when both its type and its trait are public
|
2018-11-27 02:59:49 +00:00
|
|
|
// Subitems of trait impls have inherited publicity.
|
2023-02-12 18:26:47 +00:00
|
|
|
DefKind::Impl { .. } => {
|
2025-02-03 10:45:49 +11:00
|
|
|
let item = tcx.hir_item(id);
|
2023-11-21 20:07:32 +01:00
|
|
|
if let hir::ItemKind::Impl(impl_) = item.kind {
|
2023-06-15 17:15:24 +03:00
|
|
|
let impl_vis = ty::Visibility::of_impl::<false>(
|
|
|
|
|
item.owner_id.def_id,
|
|
|
|
|
tcx,
|
|
|
|
|
&Default::default(),
|
|
|
|
|
);
|
2023-05-18 14:57:45 +03:00
|
|
|
|
2023-06-15 17:15:24 +03:00
|
|
|
// We are using the non-shallow version here, unlike when building the
|
2023-05-18 14:57:45 +03:00
|
|
|
// effective visisibilities table to avoid large number of false positives.
|
2023-06-15 17:15:24 +03:00
|
|
|
// For example in
|
2023-05-18 14:57:45 +03:00
|
|
|
//
|
|
|
|
|
// impl From<Priv> for Pub {
|
|
|
|
|
// fn from(_: Priv) -> Pub {...}
|
|
|
|
|
// }
|
|
|
|
|
//
|
2023-11-14 23:06:50 +08:00
|
|
|
// lints shouldn't be emitted even if `from` effective visibility
|
2023-06-15 17:15:24 +03:00
|
|
|
// is larger than `Priv` nominal visibility and if `Priv` can leak
|
|
|
|
|
// in some scenarios due to type inference.
|
2023-06-29 22:08:04 +03:00
|
|
|
let impl_ev = EffectiveVisibility::of_impl::<false>(
|
2023-06-15 17:15:24 +03:00
|
|
|
item.owner_id.def_id,
|
|
|
|
|
tcx,
|
|
|
|
|
self.effective_visibilities,
|
2023-06-29 22:08:04 +03:00
|
|
|
);
|
2023-05-18 14:57:45 +03:00
|
|
|
|
2022-05-05 13:34:27 -04:00
|
|
|
// check that private components do not appear in the generics or predicates of inherent impls
|
|
|
|
|
// this check is intentionally NOT performed for impls of traits, per #90586
|
|
|
|
|
if impl_.of_trait.is_none() {
|
2023-06-29 22:08:04 +03:00
|
|
|
self.check(item.owner_id.def_id, impl_vis, Some(impl_ev))
|
|
|
|
|
.generics()
|
|
|
|
|
.predicates();
|
2022-05-05 13:34:27 -04:00
|
|
|
}
|
|
|
|
|
for impl_item_ref in impl_.items {
|
|
|
|
|
let impl_item_vis = if impl_.of_trait.is_none() {
|
2022-10-27 14:02:18 +11:00
|
|
|
min(
|
|
|
|
|
tcx.local_visibility(impl_item_ref.id.owner_id.def_id),
|
|
|
|
|
impl_vis,
|
|
|
|
|
tcx,
|
|
|
|
|
)
|
2022-05-05 13:34:27 -04:00
|
|
|
} else {
|
|
|
|
|
impl_vis
|
|
|
|
|
};
|
2023-05-18 14:57:45 +03:00
|
|
|
|
|
|
|
|
let impl_item_ev = if impl_.of_trait.is_none() {
|
|
|
|
|
self.get(impl_item_ref.id.owner_id.def_id)
|
2023-06-29 22:08:04 +03:00
|
|
|
.map(|ev| ev.min(impl_ev, self.tcx))
|
2023-05-18 14:57:45 +03:00
|
|
|
} else {
|
2023-06-29 22:08:04 +03:00
|
|
|
Some(impl_ev)
|
2023-05-18 14:57:45 +03:00
|
|
|
};
|
|
|
|
|
|
2022-05-05 13:34:27 -04:00
|
|
|
self.check_assoc_item(
|
2022-10-27 14:02:18 +11:00
|
|
|
impl_item_ref.id.owner_id.def_id,
|
2022-05-05 13:34:27 -04:00
|
|
|
impl_item_ref.kind,
|
|
|
|
|
impl_item_vis,
|
2023-05-18 14:57:45 +03:00
|
|
|
impl_item_ev,
|
2022-05-05 13:34:27 -04:00
|
|
|
);
|
|
|
|
|
}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
2022-05-05 13:34:27 -04:00
|
|
|
_ => {}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-05 23:00:14 +03:00
|
|
|
pub fn provide(providers: &mut Providers) {
|
2017-03-23 15:13:29 -04:00
|
|
|
*providers = Providers {
|
2022-09-22 16:19:53 +03:00
|
|
|
effective_visibilities,
|
2019-03-06 04:50:50 +01:00
|
|
|
check_private_in_public,
|
2018-06-08 19:14:03 +02:00
|
|
|
check_mod_privacy,
|
2017-03-23 15:13:29 -04:00
|
|
|
..*providers
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-26 20:53:51 +02:00
|
|
|
fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
2017-04-16 21:19:24 +03:00
|
|
|
// Check privacy of names not checked in previous compilation stages.
|
2024-01-25 13:25:29 +03:00
|
|
|
let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None };
|
2025-02-17 14:17:57 +11:00
|
|
|
tcx.hir_visit_item_likes_in_module(module_def_id, &mut visitor);
|
2015-01-15 10:47:17 -08:00
|
|
|
|
2017-04-22 22:46:34 +03:00
|
|
|
// Check privacy of explicitly written types and traits as well as
|
|
|
|
|
// inferred types of expressions and patterns.
|
2024-01-25 13:25:29 +03:00
|
|
|
let span = tcx.def_span(module_def_id);
|
2024-01-24 00:07:00 +03:00
|
|
|
let mut visitor = TypePrivacyVisitor { tcx, module_def_id, maybe_typeck_results: None, span };
|
2023-07-18 07:22:46 +00:00
|
|
|
|
|
|
|
|
let module = tcx.hir_module_items(module_def_id);
|
|
|
|
|
for def_id in module.definitions() {
|
2025-02-22 23:55:08 +00:00
|
|
|
let _ = rustc_ty_utils::sig_types::walk_types(tcx, def_id, &mut visitor);
|
2023-07-18 07:22:46 +00:00
|
|
|
|
2025-02-17 14:17:57 +11:00
|
|
|
if let Some(body_id) = tcx.hir_maybe_body_owned_by(def_id) {
|
2024-05-29 10:03:40 +00:00
|
|
|
visitor.visit_nested_body(body_id.id());
|
2023-07-18 07:22:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-20 23:52:26 +01:00
|
|
|
for id in module.free_items() {
|
2025-02-03 10:45:49 +11:00
|
|
|
if let ItemKind::Impl(i) = tcx.hir_item(id).kind {
|
2023-07-18 07:22:46 +00:00
|
|
|
if let Some(item) = i.of_trait {
|
|
|
|
|
let trait_ref = tcx.impl_trait_ref(id.owner_id.def_id).unwrap();
|
|
|
|
|
let trait_ref = trait_ref.instantiate_identity();
|
|
|
|
|
visitor.span = item.path.span;
|
2025-02-22 23:55:08 +00:00
|
|
|
let _ = visitor.visit_def_id(
|
|
|
|
|
trait_ref.def_id,
|
|
|
|
|
"trait",
|
|
|
|
|
&trait_ref.print_only_trait_path(),
|
|
|
|
|
);
|
2023-07-18 07:22:46 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2018-06-08 19:14:03 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-22 16:19:53 +03:00
|
|
|
fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
|
2015-01-15 10:47:17 -08:00
|
|
|
// Build up a set of all exported items in the AST. This is a set of all
|
|
|
|
|
// items which are reachable from external crates based on visibility.
|
|
|
|
|
let mut visitor = EmbargoVisitor {
|
2017-08-06 22:54:09 -07:00
|
|
|
tcx,
|
2022-09-22 16:19:53 +03:00
|
|
|
effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
|
2019-08-05 23:06:02 +01:00
|
|
|
macro_reachable: Default::default(),
|
2015-11-19 14:16:35 +03:00
|
|
|
changed: false,
|
2015-01-15 10:47:17 -08:00
|
|
|
};
|
2021-07-26 05:38:16 +02:00
|
|
|
|
2023-06-15 19:07:51 +03:00
|
|
|
visitor.effective_visibilities.check_invariants(tcx);
|
2024-08-18 15:25:42 +00:00
|
|
|
|
|
|
|
|
// HACK(jynelson): trying to infer the type of `impl Trait` breaks `async-std` (and
|
|
|
|
|
// `pub async fn` in general). Since rustdoc never needs to do codegen and doesn't
|
|
|
|
|
// care about link-time reachability, keep them unreachable (issue #75100).
|
|
|
|
|
let impl_trait_pass = !tcx.sess.opts.actually_rustdoc;
|
|
|
|
|
if impl_trait_pass {
|
2023-05-08 17:43:20 +03:00
|
|
|
// Underlying types of `impl Trait`s are marked as reachable unconditionally,
|
|
|
|
|
// so this pass doesn't need to be a part of the fixed point iteration below.
|
2024-08-18 15:25:42 +00:00
|
|
|
let krate = tcx.hir_crate_items(());
|
|
|
|
|
for id in krate.opaques() {
|
|
|
|
|
let opaque = tcx.hir_node_by_def_id(id).expect_opaque_ty();
|
|
|
|
|
let should_visit = match opaque.origin {
|
|
|
|
|
hir::OpaqueTyOrigin::FnReturn {
|
|
|
|
|
parent,
|
|
|
|
|
in_trait_or_impl: Some(hir::RpitContext::Trait),
|
|
|
|
|
}
|
|
|
|
|
| hir::OpaqueTyOrigin::AsyncFn {
|
|
|
|
|
parent,
|
|
|
|
|
in_trait_or_impl: Some(hir::RpitContext::Trait),
|
|
|
|
|
} => match tcx.hir_node_by_def_id(parent).expect_trait_item().expect_fn().1 {
|
|
|
|
|
hir::TraitFn::Required(_) => false,
|
|
|
|
|
hir::TraitFn::Provided(..) => true,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// Always visit RPITs in functions that have definitions,
|
|
|
|
|
// and all TAITs.
|
|
|
|
|
hir::OpaqueTyOrigin::FnReturn {
|
|
|
|
|
in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
|
|
|
|
|
..
|
|
|
|
|
}
|
|
|
|
|
| hir::OpaqueTyOrigin::AsyncFn {
|
|
|
|
|
in_trait_or_impl: None | Some(hir::RpitContext::TraitImpl),
|
|
|
|
|
..
|
|
|
|
|
}
|
|
|
|
|
| hir::OpaqueTyOrigin::TyAlias { .. } => true,
|
|
|
|
|
};
|
|
|
|
|
if should_visit {
|
|
|
|
|
// FIXME: This is some serious pessimization intended to workaround deficiencies
|
|
|
|
|
// in the reachability pass (`middle/reachable.rs`). Types are marked as link-time
|
|
|
|
|
// reachable if they are returned via `impl Trait`, even from private functions.
|
|
|
|
|
let pub_ev = EffectiveVisibility::from_vis(ty::Visibility::Public);
|
|
|
|
|
visitor
|
|
|
|
|
.reach_through_impl_trait(opaque.def_id, pub_ev)
|
|
|
|
|
.generics()
|
|
|
|
|
.predicates()
|
|
|
|
|
.ty();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-08 17:43:20 +03:00
|
|
|
visitor.changed = false;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-15 10:47:17 -08:00
|
|
|
loop {
|
2025-02-17 14:17:57 +11:00
|
|
|
tcx.hir_visit_all_item_likes_in_crate(&mut visitor);
|
2015-11-19 14:16:35 +03:00
|
|
|
if visitor.changed {
|
|
|
|
|
visitor.changed = false;
|
|
|
|
|
} else {
|
2015-01-15 10:47:17 -08:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-06-15 19:07:51 +03:00
|
|
|
visitor.effective_visibilities.check_invariants(tcx);
|
2015-11-26 19:26:15 +03:00
|
|
|
|
2022-09-22 16:19:53 +03:00
|
|
|
let mut check_visitor =
|
|
|
|
|
TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
|
2023-03-28 20:26:41 +04:00
|
|
|
check_visitor.effective_visibility_diagnostic(CRATE_DEF_ID);
|
2025-02-17 14:17:57 +11:00
|
|
|
tcx.hir_visit_all_item_likes_in_crate(&mut check_visitor);
|
2022-08-14 17:05:17 +03:00
|
|
|
|
2022-09-22 16:19:53 +03:00
|
|
|
tcx.arena.alloc(visitor.effective_visibilities)
|
2019-02-23 16:40:15 +01:00
|
|
|
}
|
2015-11-26 19:26:15 +03:00
|
|
|
|
2021-05-11 13:49:00 +02:00
|
|
|
fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
|
2022-09-22 16:19:53 +03:00
|
|
|
let effective_visibilities = tcx.effective_visibilities(());
|
2023-06-19 17:06:00 +03:00
|
|
|
// Check for private types in public interfaces.
|
|
|
|
|
let mut checker = PrivateItemsInPublicInterfacesChecker { tcx, effective_visibilities };
|
2022-05-05 13:34:27 -04:00
|
|
|
|
2025-02-03 10:45:49 +11:00
|
|
|
for id in tcx.hir_free_items() {
|
2022-05-05 13:34:27 -04:00
|
|
|
checker.check_item(id);
|
|
|
|
|
}
|
2015-01-15 10:47:17 -08:00
|
|
|
}
|