summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_privacy
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_privacy/Cargo.toml2
-rw-r--r--compiler/rustc_privacy/src/errors.rs42
-rw-r--r--compiler/rustc_privacy/src/lib.rs342
3 files changed, 214 insertions, 172 deletions
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index 5785921fb..832fdc9f0 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -14,5 +14,5 @@ rustc_middle = { path = "../rustc_middle" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_trait_selection = { path = "../rustc_trait_selection" }
-rustc_typeck = { path = "../rustc_typeck" }
+rustc_hir_analysis = { path = "../rustc_hir_analysis" }
tracing = "0.1"
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index 63f83f896..a6c95f1a8 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -1,9 +1,9 @@
use rustc_errors::DiagnosticArgFromDisplay;
-use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
+use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
use rustc_span::{Span, Symbol};
-#[derive(SessionDiagnostic)]
-#[diag(privacy::field_is_private, code = "E0451")]
+#[derive(Diagnostic)]
+#[diag(privacy_field_is_private, code = "E0451")]
pub struct FieldIsPrivate {
#[primary_span]
pub span: Span,
@@ -14,23 +14,23 @@ pub struct FieldIsPrivate {
pub label: FieldIsPrivateLabel,
}
-#[derive(SessionSubdiagnostic)]
+#[derive(Subdiagnostic)]
pub enum FieldIsPrivateLabel {
- #[label(privacy::field_is_private_is_update_syntax_label)]
+ #[label(privacy_field_is_private_is_update_syntax_label)]
IsUpdateSyntax {
#[primary_span]
span: Span,
field_name: Symbol,
},
- #[label(privacy::field_is_private_label)]
+ #[label(privacy_field_is_private_label)]
Other {
#[primary_span]
span: Span,
},
}
-#[derive(SessionDiagnostic)]
-#[diag(privacy::item_is_private)]
+#[derive(Diagnostic)]
+#[diag(privacy_item_is_private)]
pub struct ItemIsPrivate<'a> {
#[primary_span]
#[label]
@@ -39,8 +39,8 @@ pub struct ItemIsPrivate<'a> {
pub descr: DiagnosticArgFromDisplay<'a>,
}
-#[derive(SessionDiagnostic)]
-#[diag(privacy::unnamed_item_is_private)]
+#[derive(Diagnostic)]
+#[diag(privacy_unnamed_item_is_private)]
pub struct UnnamedItemIsPrivate {
#[primary_span]
pub span: Span,
@@ -48,8 +48,8 @@ pub struct UnnamedItemIsPrivate {
}
// Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
-#[derive(SessionDiagnostic)]
-#[diag(privacy::in_public_interface, code = "E0445")]
+#[derive(Diagnostic)]
+#[diag(privacy_in_public_interface, code = "E0445")]
pub struct InPublicInterfaceTraits<'a> {
#[primary_span]
#[label]
@@ -57,13 +57,13 @@ pub struct InPublicInterfaceTraits<'a> {
pub vis_descr: &'static str,
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
- #[label(privacy::visibility_label)]
+ #[label(visibility_label)]
pub vis_span: Span,
}
// Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
-#[derive(SessionDiagnostic)]
-#[diag(privacy::in_public_interface, code = "E0446")]
+#[derive(Diagnostic)]
+#[diag(privacy_in_public_interface, code = "E0446")]
pub struct InPublicInterface<'a> {
#[primary_span]
#[label]
@@ -71,20 +71,20 @@ pub struct InPublicInterface<'a> {
pub vis_descr: &'static str,
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
- #[label(privacy::visibility_label)]
+ #[label(visibility_label)]
pub vis_span: Span,
}
-#[derive(SessionDiagnostic)]
-#[diag(privacy::report_access_level)]
-pub struct ReportAccessLevel {
+#[derive(Diagnostic)]
+#[diag(privacy_report_effective_visibility)]
+pub struct ReportEffectiveVisibility {
#[primary_span]
pub span: Span,
pub descr: String,
}
#[derive(LintDiagnostic)]
-#[diag(privacy::from_private_dep_in_public_interface)]
+#[diag(privacy_from_private_dep_in_public_interface)]
pub struct FromPrivateDependencyInPublicInterface<'a> {
pub kind: &'a str,
pub descr: DiagnosticArgFromDisplay<'a>,
@@ -92,7 +92,7 @@ pub struct FromPrivateDependencyInPublicInterface<'a> {
}
#[derive(LintDiagnostic)]
-#[diag(privacy::private_in_public_lint)]
+#[diag(privacy_private_in_public_lint)]
pub struct PrivateInPublicLint<'a> {
pub vis_descr: &'static str,
pub kind: &'a str,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 48ab31ab9..865d6306b 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1,7 +1,6 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(associated_type_defaults)]
#![feature(control_flow_enum)]
-#![cfg_attr(bootstrap, feature(let_else))]
#![feature(rustc_private)]
#![feature(try_blocks)]
#![recursion_limit = "256"]
@@ -24,7 +23,7 @@ use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind};
use rustc_middle::bug;
use rustc_middle::hir::nested_filter;
-use rustc_middle::middle::privacy::{AccessLevel, AccessLevels};
+use rustc_middle::middle::privacy::{EffectiveVisibilities, Level};
use rustc_middle::span_bug;
use rustc_middle::ty::abstract_const::{walk_abstract_const, AbstractConst, Node as ACNode};
use rustc_middle::ty::query::Providers;
@@ -42,7 +41,7 @@ use std::{cmp, fmt, mem};
use errors::{
FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface,
- InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportAccessLevel,
+ InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportEffectiveVisibility,
UnnamedItemIsPrivate,
};
@@ -123,8 +122,20 @@ where
&mut self,
projection: ty::ProjectionTy<'tcx>,
) -> ControlFlow<V::BreakTy> {
- let (trait_ref, assoc_substs) =
- projection.trait_ref_and_own_substs(self.def_id_visitor.tcx());
+ let tcx = self.def_id_visitor.tcx();
+ let (trait_ref, assoc_substs) = if tcx.def_kind(projection.item_def_id)
+ != DefKind::ImplTraitPlaceholder
+ {
+ projection.trait_ref_and_own_substs(tcx)
+ } else {
+ // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
+ let def_id = tcx.impl_trait_in_trait_parent(projection.item_def_id);
+ let trait_generics = tcx.generics_of(def_id);
+ (
+ ty::TraitRef { def_id, substs: projection.substs.truncate_to(tcx, trait_generics) },
+ &projection.substs[trait_generics.count()..],
+ )
+ };
self.visit_trait(trait_ref)?;
if self.def_id_visitor.shallow() {
ControlFlow::CONTINUE
@@ -148,34 +159,12 @@ where
ty.visit_with(self)
}
ty::PredicateKind::RegionOutlives(..) => ControlFlow::CONTINUE,
- ty::PredicateKind::ConstEvaluatable(uv)
- if self.def_id_visitor.tcx().features().generic_const_exprs =>
- {
- let tcx = self.def_id_visitor.tcx();
- if let Ok(Some(ct)) = AbstractConst::new(tcx, uv) {
- self.visit_abstract_const_expr(tcx, ct)?;
- }
- ControlFlow::CONTINUE
- }
+ ty::PredicateKind::ConstEvaluatable(ct) => ct.visit_with(self),
ty::PredicateKind::WellFormed(arg) => arg.visit_with(self),
_ => bug!("unexpected predicate: {:?}", predicate),
}
}
- fn visit_abstract_const_expr(
- &mut self,
- tcx: TyCtxt<'tcx>,
- ct: AbstractConst<'tcx>,
- ) -> ControlFlow<V::BreakTy> {
- walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
- ACNode::Leaf(leaf) => self.visit_const(leaf),
- ACNode::Cast(_, _, ty) => self.visit_ty(ty),
- ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
- ControlFlow::CONTINUE
- }
- })
- }
-
fn visit_predicates(
&mut self,
predicates: ty::GenericPredicates<'tcx>,
@@ -298,9 +287,16 @@ where
self.visit_ty(c.ty())?;
let tcx = self.def_id_visitor.tcx();
if let Ok(Some(ct)) = AbstractConst::from_const(tcx, c) {
- self.visit_abstract_const_expr(tcx, ct)?;
+ walk_abstract_const(tcx, ct, |node| match node.root(tcx) {
+ ACNode::Leaf(leaf) => self.visit_const(leaf),
+ ACNode::Cast(_, _, ty) => self.visit_ty(ty),
+ ACNode::Binop(..) | ACNode::UnaryOp(..) | ACNode::FunctionCall(_, _) => {
+ ControlFlow::CONTINUE
+ }
+ })
+ } else {
+ ControlFlow::CONTINUE
}
- ControlFlow::CONTINUE
}
}
@@ -314,7 +310,7 @@ fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visib
struct FindMin<'a, 'tcx, VL: VisibilityLike> {
tcx: TyCtxt<'tcx>,
- access_levels: &'a AccessLevels,
+ effective_visibilities: &'a EffectiveVisibilities,
min: VL,
}
@@ -348,8 +344,12 @@ trait VisibilityLike: Sized {
// Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
// associated types for which we can't determine visibility precisely.
- fn of_impl(def_id: LocalDefId, tcx: TyCtxt<'_>, access_levels: &AccessLevels) -> Self {
- let mut find = FindMin { tcx, access_levels, min: Self::MAX };
+ fn of_impl(
+ def_id: LocalDefId,
+ tcx: TyCtxt<'_>,
+ effective_visibilities: &EffectiveVisibilities,
+ ) -> Self {
+ let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX };
find.visit(tcx.type_of(def_id));
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
find.visit_trait(trait_ref);
@@ -363,8 +363,8 @@ impl VisibilityLike for ty::Visibility {
min(find.tcx.local_visibility(def_id), find.min, find.tcx)
}
}
-impl VisibilityLike for Option<AccessLevel> {
- const MAX: Self = Some(AccessLevel::Public);
+impl VisibilityLike for Option<Level> {
+ const MAX: Self = Some(Level::Direct);
// 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> { ... }`
@@ -376,7 +376,7 @@ impl VisibilityLike for Option<AccessLevel> {
// (which require reaching the `DefId`s in them).
const SHALLOW: bool = true;
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
- cmp::min(find.access_levels.map.get(&def_id).copied(), find.min)
+ cmp::min(find.effective_visibilities.public_at_level(def_id), find.min)
}
}
@@ -387,8 +387,8 @@ impl VisibilityLike for Option<AccessLevel> {
struct EmbargoVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
- /// Accessibility levels for reachable nodes.
- access_levels: AccessLevels,
+ /// Effective visibilities for reachable nodes.
+ effective_visibilities: EffectiveVisibilities,
/// 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:
@@ -402,38 +402,38 @@ struct EmbargoVisitor<'tcx> {
/// n::p::f()
/// }
macro_reachable: FxHashSet<(LocalDefId, LocalDefId)>,
- /// Previous accessibility level; `None` means unreachable.
- prev_level: Option<AccessLevel>,
+ /// Previous visibility level; `None` means unreachable.
+ prev_level: Option<Level>,
/// Has something changed in the level map?
changed: bool,
}
struct ReachEverythingInTheInterfaceVisitor<'a, 'tcx> {
- access_level: Option<AccessLevel>,
+ level: Option<Level>,
item_def_id: LocalDefId,
ev: &'a mut EmbargoVisitor<'tcx>,
}
impl<'tcx> EmbargoVisitor<'tcx> {
- fn get(&self, def_id: LocalDefId) -> Option<AccessLevel> {
- self.access_levels.map.get(&def_id).copied()
+ fn get(&self, def_id: LocalDefId) -> Option<Level> {
+ self.effective_visibilities.public_at_level(def_id)
}
- fn update_with_hir_id(
- &mut self,
- hir_id: hir::HirId,
- level: Option<AccessLevel>,
- ) -> Option<AccessLevel> {
+ fn update_with_hir_id(&mut self, hir_id: hir::HirId, level: Option<Level>) -> Option<Level> {
let def_id = self.tcx.hir().local_def_id(hir_id);
self.update(def_id, level)
}
/// Updates node level and returns the updated level.
- fn update(&mut self, def_id: LocalDefId, level: Option<AccessLevel>) -> Option<AccessLevel> {
+ fn update(&mut self, def_id: LocalDefId, level: Option<Level>) -> Option<Level> {
let old_level = self.get(def_id);
- // Accessibility levels can only grow.
+ // Visibility levels can only grow.
if level > old_level {
- self.access_levels.map.insert(def_id, level.unwrap());
+ self.effective_visibilities.set_public_at_level(
+ def_id,
+ || ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)),
+ level.unwrap(),
+ );
self.changed = true;
level
} else {
@@ -444,10 +444,10 @@ impl<'tcx> EmbargoVisitor<'tcx> {
fn reach(
&mut self,
def_id: LocalDefId,
- access_level: Option<AccessLevel>,
+ level: Option<Level>,
) -> ReachEverythingInTheInterfaceVisitor<'_, 'tcx> {
ReachEverythingInTheInterfaceVisitor {
- access_level: cmp::min(access_level, Some(AccessLevel::Reachable)),
+ level: cmp::min(level, Some(Level::Reachable)),
item_def_id: def_id,
ev: self,
}
@@ -505,9 +505,9 @@ impl<'tcx> EmbargoVisitor<'tcx> {
fn update_macro_reachable_mod(&mut self, module_def_id: LocalDefId, defining_mod: LocalDefId) {
let module = self.tcx.hir().get_module(module_def_id).0;
for item_id in module.item_ids {
- let def_kind = self.tcx.def_kind(item_id.def_id);
- let vis = self.tcx.local_visibility(item_id.def_id);
- self.update_macro_reachable_def(item_id.def_id, def_kind, vis, defining_mod);
+ let def_kind = self.tcx.def_kind(item_id.owner_id);
+ let vis = self.tcx.local_visibility(item_id.owner_id.def_id);
+ self.update_macro_reachable_def(item_id.owner_id.def_id, def_kind, vis, defining_mod);
}
if let Some(exports) = self.tcx.module_reexports(module_def_id) {
for export in exports {
@@ -530,7 +530,7 @@ impl<'tcx> EmbargoVisitor<'tcx> {
vis: ty::Visibility,
module: LocalDefId,
) {
- let level = Some(AccessLevel::Reachable);
+ let level = Some(Level::Reachable);
if vis.is_public() {
self.update(def_id, level);
}
@@ -627,11 +627,14 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
let item_level = match item.kind {
hir::ItemKind::Impl { .. } => {
- let impl_level =
- Option::<AccessLevel>::of_impl(item.def_id, self.tcx, &self.access_levels);
- self.update(item.def_id, impl_level)
+ let impl_level = Option::<Level>::of_impl(
+ item.owner_id.def_id,
+ self.tcx,
+ &self.effective_visibilities,
+ );
+ self.update(item.owner_id.def_id, impl_level)
}
- _ => self.get(item.def_id),
+ _ => self.get(item.owner_id.def_id),
};
// Update levels of nested things.
@@ -650,15 +653,15 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
hir::ItemKind::Impl(ref impl_) => {
for impl_item_ref in impl_.items {
if impl_.of_trait.is_some()
- || self.tcx.visibility(impl_item_ref.id.def_id).is_public()
+ || self.tcx.visibility(impl_item_ref.id.owner_id).is_public()
{
- self.update(impl_item_ref.id.def_id, item_level);
+ self.update(impl_item_ref.id.owner_id.def_id, item_level);
}
}
}
hir::ItemKind::Trait(.., trait_item_refs) => {
for trait_item_ref in trait_item_refs {
- self.update(trait_item_ref.id.def_id, item_level);
+ self.update(trait_item_ref.id.owner_id.def_id, item_level);
}
}
hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
@@ -674,12 +677,12 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
}
hir::ItemKind::Macro(ref macro_def, _) => {
- self.update_reachability_from_macro(item.def_id, macro_def);
+ self.update_reachability_from_macro(item.owner_id.def_id, macro_def);
}
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- if self.tcx.visibility(foreign_item.id.def_id).is_public() {
- self.update(foreign_item.id.def_id, item_level);
+ if self.tcx.visibility(foreign_item.id.owner_id).is_public() {
+ self.update(foreign_item.id.owner_id.def_id, item_level);
}
}
}
@@ -702,7 +705,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
hir::ItemKind::Macro(..) | hir::ItemKind::ExternCrate(..) => {}
// All nested items are checked by `visit_item`.
hir::ItemKind::Mod(..) => {}
- // Handled in the access level of in rustc_resolve
+ // Handled in `rustc_resolve`.
hir::ItemKind::Use(..) => {}
// The interface is empty.
hir::ItemKind::GlobalAsm(..) => {}
@@ -715,9 +718,8 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// 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 exist_level =
- cmp::max(item_level, Some(AccessLevel::ReachableFromImplTrait));
- self.reach(item.def_id, exist_level).generics().predicates().ty();
+ let exist_level = cmp::max(item_level, Some(Level::ReachableThroughImplTrait));
+ self.reach(item.owner_id.def_id, exist_level).generics().predicates().ty();
}
}
// Visit everything.
@@ -726,20 +728,20 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
| hir::ItemKind::Fn(..)
| hir::ItemKind::TyAlias(..) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates().ty();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates().ty();
}
}
hir::ItemKind::Trait(.., trait_item_refs) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates();
for trait_item_ref in trait_item_refs {
let tcx = self.tcx;
- let mut reach = self.reach(trait_item_ref.id.def_id, item_level);
+ let mut reach = self.reach(trait_item_ref.id.owner_id.def_id, item_level);
reach.generics().predicates();
if trait_item_ref.kind == AssocItemKind::Type
- && !tcx.impl_defaultness(trait_item_ref.id.def_id).has_value()
+ && !tcx.impl_defaultness(trait_item_ref.id.owner_id).has_value()
{
// No type to visit.
} else {
@@ -750,18 +752,22 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
hir::ItemKind::TraitAlias(..) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates();
}
}
// Visit everything except for private impl items.
hir::ItemKind::Impl(ref impl_) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates().ty().trait_ref();
+ self.reach(item.owner_id.def_id, item_level)
+ .generics()
+ .predicates()
+ .ty()
+ .trait_ref();
for impl_item_ref in impl_.items {
- let impl_item_level = self.get(impl_item_ref.id.def_id);
+ let impl_item_level = self.get(impl_item_ref.id.owner_id.def_id);
if impl_item_level.is_some() {
- self.reach(impl_item_ref.id.def_id, impl_item_level)
+ self.reach(impl_item_ref.id.owner_id.def_id, impl_item_level)
.generics()
.predicates()
.ty();
@@ -773,7 +779,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// Visit everything, but enum variants have their own levels.
hir::ItemKind::Enum(ref def, _) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates();
}
for variant in def.variants {
let variant_level = self.get(self.tcx.hir().local_def_id(variant.id));
@@ -784,13 +790,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
// Corner case: if the variant is reachable, but its
// enum is not, make the enum reachable as well.
- self.reach(item.def_id, variant_level).ty();
+ self.reach(item.owner_id.def_id, variant_level).ty();
}
if let Some(hir_id) = variant.data.ctor_hir_id() {
let ctor_def_id = self.tcx.hir().local_def_id(hir_id);
let ctor_level = self.get(ctor_def_id);
if ctor_level.is_some() {
- self.reach(item.def_id, ctor_level).ty();
+ self.reach(item.owner_id.def_id, ctor_level).ty();
}
}
}
@@ -798,9 +804,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// Visit everything, but foreign items have their own levels.
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- let foreign_item_level = self.get(foreign_item.id.def_id);
+ let foreign_item_level = self.get(foreign_item.id.owner_id.def_id);
if foreign_item_level.is_some() {
- self.reach(foreign_item.id.def_id, foreign_item_level)
+ self.reach(foreign_item.id.owner_id.def_id, foreign_item_level)
.generics()
.predicates()
.ty();
@@ -810,7 +816,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
// Visit everything except for private fields.
hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => {
if item_level.is_some() {
- self.reach(item.def_id, item_level).generics().predicates();
+ self.reach(item.owner_id.def_id, item_level).generics().predicates();
for field in struct_def.fields() {
let def_id = self.tcx.hir().local_def_id(field.hir_id);
let field_level = self.get(def_id);
@@ -823,7 +829,7 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
let ctor_def_id = self.tcx.hir().local_def_id(hir_id);
let ctor_level = self.get(ctor_def_id);
if ctor_level.is_some() {
- self.reach(item.def_id, ctor_level).ty();
+ self.reach(item.owner_id.def_id, ctor_level).ty();
}
}
}
@@ -894,10 +900,10 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
_descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> {
if let Some(def_id) = def_id.as_local() {
- if let (ty::Visibility::Public, _) | (_, Some(AccessLevel::ReachableFromImplTrait)) =
- (self.tcx().visibility(def_id.to_def_id()), self.access_level)
+ if let (ty::Visibility::Public, _) | (_, Some(Level::ReachableThroughImplTrait)) =
+ (self.tcx().visibility(def_id.to_def_id()), self.level)
{
- self.ev.update(def_id, self.access_level);
+ self.ev.update(def_id, self.level);
}
}
ControlFlow::CONTINUE
@@ -905,42 +911,64 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
}
////////////////////////////////////////////////////////////////////////////////
-/// Visitor, used for AccessLevels table checking
+/// Visitor, used for EffectiveVisibilities table checking
////////////////////////////////////////////////////////////////////////////////
pub struct TestReachabilityVisitor<'tcx, 'a> {
tcx: TyCtxt<'tcx>,
- access_levels: &'a AccessLevels,
+ effective_visibilities: &'a EffectiveVisibilities,
}
impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> {
- fn access_level_diagnostic(&mut self, def_id: LocalDefId) {
- if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_access_level) {
- let access_level = format!("{:?}", self.access_levels.map.get(&def_id));
+ fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) {
+ if self.tcx.has_attr(def_id.to_def_id(), sym::rustc_effective_visibility) {
+ let mut error_msg = String::new();
let span = self.tcx.def_span(def_id.to_def_id());
- self.tcx.sess.emit_err(ReportAccessLevel { span, descr: access_level });
+ if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) {
+ for level in Level::all_levels() {
+ let vis_str = match effective_vis.at_level(level) {
+ ty::Visibility::Restricted(restricted_id) => {
+ if restricted_id.is_top_level_module() {
+ "pub(crate)".to_string()
+ } else if *restricted_id == self.tcx.parent_module_from_def_id(def_id) {
+ "pub(self)".to_string()
+ } else {
+ format!("pub({})", self.tcx.item_name(restricted_id.to_def_id()))
+ }
+ }
+ ty::Visibility::Public => "pub".to_string(),
+ };
+ if level != Level::Direct {
+ error_msg.push_str(", ");
+ }
+ error_msg.push_str(&format!("{:?}: {}", level, vis_str));
+ }
+ } else {
+ error_msg.push_str("not in the table");
+ }
+ self.tcx.sess.emit_err(ReportEffectiveVisibility { span, descr: error_msg });
}
}
}
impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- self.access_level_diagnostic(item.def_id);
+ self.effective_visibility_diagnostic(item.owner_id.def_id);
match item.kind {
hir::ItemKind::Enum(ref def, _) => {
for variant in def.variants.iter() {
let variant_id = self.tcx.hir().local_def_id(variant.id);
- self.access_level_diagnostic(variant_id);
+ self.effective_visibility_diagnostic(variant_id);
for field in variant.data.fields() {
let def_id = self.tcx.hir().local_def_id(field.hir_id);
- self.access_level_diagnostic(def_id);
+ self.effective_visibility_diagnostic(def_id);
}
}
}
hir::ItemKind::Struct(ref def, _) | hir::ItemKind::Union(ref def, _) => {
for field in def.fields() {
let def_id = self.tcx.hir().local_def_id(field.hir_id);
- self.access_level_diagnostic(def_id);
+ self.effective_visibility_diagnostic(def_id);
}
}
_ => {}
@@ -948,13 +976,13 @@ impl<'tcx, 'a> Visitor<'tcx> for TestReachabilityVisitor<'tcx, 'a> {
}
fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem<'tcx>) {
- self.access_level_diagnostic(item.def_id);
+ self.effective_visibility_diagnostic(item.owner_id.def_id);
}
fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem<'tcx>) {
- self.access_level_diagnostic(item.def_id);
+ self.effective_visibility_diagnostic(item.owner_id.def_id);
}
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
- self.access_level_diagnostic(item.def_id);
+ self.effective_visibility_diagnostic(item.owner_id.def_id);
}
}
@@ -1025,7 +1053,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
// Don't visit nested modules, since we run a separate visitor walk
- // for each module in `privacy_access_levels`
+ // for each module in `effective_visibilities`
}
fn visit_nested_body(&mut self, body: hir::BodyId) {
@@ -1037,7 +1065,7 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> {
}
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- let orig_current_item = mem::replace(&mut self.current_item, item.def_id);
+ let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id);
intravisit::walk_item(self, item);
self.current_item = orig_current_item;
}
@@ -1150,7 +1178,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) {
// Don't visit nested modules, since we run a separate visitor walk
- // for each module in `privacy_access_levels`
+ // for each module in `effective_visibilities`
}
fn visit_nested_body(&mut self, body: hir::BodyId) {
@@ -1180,7 +1208,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
// Types in signatures.
// FIXME: This is very ineffective. Ideally each HIR type should be converted
// into a semantic type only once and the result should be cached somehow.
- if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty)).is_break() {
+ if self.visit(rustc_hir_analysis::hir_ty_to_ty(self.tcx, hir_ty)).is_break() {
return;
}
}
@@ -1209,7 +1237,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
if self.maybe_typeck_results.is_none() {
// Avoid calling `hir_trait_to_predicates` in bodies, it will ICE.
// The traits' privacy in bodies is already checked as a part of trait object types.
- let bounds = rustc_typeck::hir_trait_to_predicates(
+ let bounds = rustc_hir_analysis::hir_trait_to_predicates(
self.tcx,
trait_ref,
// NOTE: This isn't really right, but the actual type doesn't matter here. It's
@@ -1340,7 +1368,7 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> {
// Check types in item interfaces.
fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) {
- let orig_current_item = mem::replace(&mut self.current_item, item.def_id);
+ let orig_current_item = mem::replace(&mut self.current_item, item.owner_id.def_id);
let old_maybe_typeck_results = self.maybe_typeck_results.take();
intravisit::walk_item(self, item);
self.maybe_typeck_results = old_maybe_typeck_results;
@@ -1375,7 +1403,7 @@ impl<'tcx> DefIdVisitor<'tcx> for TypePrivacyVisitor<'tcx> {
struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
- access_levels: &'a AccessLevels,
+ effective_visibilities: &'a EffectiveVisibilities,
in_variant: bool,
// Set of errors produced by this obsolete visitor.
old_error_set: HirIdSet,
@@ -1395,7 +1423,9 @@ struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
fn path_is_private_type(&self, path: &hir::Path<'_>) -> bool {
let did = match path.res {
- Res::PrimTy(..) | Res::SelfTy { .. } | Res::Err => return false,
+ Res::PrimTy(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } | Res::Err => {
+ return false;
+ }
res => res.def_id(),
};
@@ -1416,7 +1446,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
fn trait_is_public(&self, trait_id: LocalDefId) -> bool {
// FIXME: this would preferably be using `exported_items`, but all
// traits are exported currently (see `EmbargoVisitor.exported_trait`).
- self.access_levels.is_public(trait_id)
+ self.effective_visibilities.is_directly_public(trait_id)
}
fn check_generic_bound(&mut self, bound: &hir::GenericBound<'_>) {
@@ -1428,7 +1458,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn item_is_public(&self, def_id: LocalDefId) -> bool {
- self.access_levels.is_reachable(def_id) || self.tcx.visibility(def_id).is_public()
+ self.effective_visibilities.is_reachable(def_id) || self.tcx.visibility(def_id).is_public()
}
}
@@ -1482,7 +1512,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
hir::ItemKind::ForeignMod { .. } => {}
hir::ItemKind::Trait(.., bounds, _) => {
- if !self.trait_is_public(item.def_id) {
+ if !self.trait_is_public(item.owner_id.def_id) {
return;
}
@@ -1542,10 +1572,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|| impl_.items.iter().any(|impl_item_ref| {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item.kind {
- hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => {
- self.access_levels.is_reachable(impl_item_ref.id.def_id)
- }
- hir::ImplItemKind::TyAlias(_) => false,
+ hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => self
+ .effective_visibilities
+ .is_reachable(impl_item_ref.id.owner_id.def_id),
+ hir::ImplItemKind::Type(_) => false,
}
});
@@ -1563,11 +1593,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item.kind {
hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..)
- if self.item_is_public(impl_item.def_id) =>
+ if self.item_is_public(impl_item.owner_id.def_id) =>
{
intravisit::walk_impl_item(self, impl_item)
}
- hir::ImplItemKind::TyAlias(..) => {
+ hir::ImplItemKind::Type(..) => {
intravisit::walk_impl_item(self, impl_item)
}
_ => {}
@@ -1593,7 +1623,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
// Those in 3. are warned with this call.
for impl_item_ref in impl_.items {
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
- if let hir::ImplItemKind::TyAlias(ty) = impl_item.kind {
+ if let hir::ImplItemKind::Type(ty) = impl_item.kind {
self.visit_ty(ty);
}
}
@@ -1604,8 +1634,10 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
// methods will be visible as `Public::foo`.
let mut found_pub_static = false;
for impl_item_ref in impl_.items {
- if self.access_levels.is_reachable(impl_item_ref.id.def_id)
- || self.tcx.visibility(impl_item_ref.id.def_id).is_public()
+ if self
+ .effective_visibilities
+ .is_reachable(impl_item_ref.id.owner_id.def_id)
+ || self.tcx.visibility(impl_item_ref.id.owner_id).is_public()
{
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
match impl_item_ref.kind {
@@ -1633,7 +1665,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
hir::ItemKind::TyAlias(..) => return,
// Not at all public, so we don't care.
- _ if !self.item_is_public(item.def_id) => {
+ _ if !self.item_is_public(item.owner_id.def_id) => {
return;
}
@@ -1664,7 +1696,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem<'tcx>) {
- if self.access_levels.is_reachable(item.def_id) {
+ if self.effective_visibilities.is_reachable(item.owner_id.def_id) {
intravisit::walk_foreign_item(self, item)
}
}
@@ -1679,7 +1711,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
}
fn visit_variant(&mut self, v: &'tcx hir::Variant<'tcx>) {
- if self.access_levels.is_reachable(self.tcx.hir().local_def_id(v.id)) {
+ if self.effective_visibilities.is_reachable(self.tcx.hir().local_def_id(v.id)) {
self.in_variant = true;
intravisit::walk_variant(self, v);
self.in_variant = false;
@@ -1901,43 +1933,44 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
pub fn check_item(&mut self, id: ItemId) {
let tcx = self.tcx;
- let item_visibility = tcx.local_visibility(id.def_id);
- let def_kind = tcx.def_kind(id.def_id);
+ let def_id = id.owner_id.def_id;
+ let item_visibility = tcx.local_visibility(def_id);
+ let def_kind = tcx.def_kind(def_id);
match def_kind {
DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => {
- self.check(id.def_id, item_visibility).generics().predicates().ty();
+ self.check(def_id, item_visibility).generics().predicates().ty();
}
DefKind::OpaqueTy => {
// `ty()` for opaque types is the underlying type,
// it's not a part of interface, so we skip it.
- self.check(id.def_id, item_visibility).generics().bounds();
+ self.check(def_id, item_visibility).generics().bounds();
}
DefKind::Trait => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind {
- self.check(item.def_id, item_visibility).generics().predicates();
+ self.check(item.owner_id.def_id, item_visibility).generics().predicates();
for trait_item_ref in trait_item_refs {
self.check_assoc_item(
- trait_item_ref.id.def_id,
+ trait_item_ref.id.owner_id.def_id,
trait_item_ref.kind,
item_visibility,
);
if let AssocItemKind::Type = trait_item_ref.kind {
- self.check(trait_item_ref.id.def_id, item_visibility).bounds();
+ self.check(trait_item_ref.id.owner_id.def_id, item_visibility).bounds();
}
}
}
}
DefKind::TraitAlias => {
- self.check(id.def_id, item_visibility).generics().predicates();
+ self.check(def_id, item_visibility).generics().predicates();
}
DefKind::Enum => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Enum(ref def, _) = item.kind {
- self.check(item.def_id, item_visibility).generics().predicates();
+ self.check(item.owner_id.def_id, item_visibility).generics().predicates();
for variant in def.variants {
for field in variant.data.fields() {
@@ -1952,8 +1985,11 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
let item = tcx.hir().item(id);
if let hir::ItemKind::ForeignMod { items, .. } = item.kind {
for foreign_item in items {
- let vis = tcx.local_visibility(foreign_item.id.def_id);
- self.check(foreign_item.id.def_id, vis).generics().predicates().ty();
+ let vis = tcx.local_visibility(foreign_item.id.owner_id.def_id);
+ self.check(foreign_item.id.owner_id.def_id, vis)
+ .generics()
+ .predicates()
+ .ty();
}
}
}
@@ -1963,7 +1999,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
if let hir::ItemKind::Struct(ref struct_def, _)
| hir::ItemKind::Union(ref struct_def, _) = item.kind
{
- self.check(item.def_id, item_visibility).generics().predicates();
+ self.check(item.owner_id.def_id, item_visibility).generics().predicates();
for field in struct_def.fields() {
let def_id = tcx.hir().local_def_id(field.hir_id);
@@ -1979,20 +2015,25 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
DefKind::Impl => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Impl(ref impl_) = item.kind {
- let impl_vis = ty::Visibility::of_impl(item.def_id, tcx, &Default::default());
+ let impl_vis =
+ ty::Visibility::of_impl(item.owner_id.def_id, tcx, &Default::default());
// 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() {
- self.check(item.def_id, impl_vis).generics().predicates();
+ self.check(item.owner_id.def_id, impl_vis).generics().predicates();
}
for impl_item_ref in impl_.items {
let impl_item_vis = if impl_.of_trait.is_none() {
- min(tcx.local_visibility(impl_item_ref.id.def_id), impl_vis, tcx)
+ min(
+ tcx.local_visibility(impl_item_ref.id.owner_id.def_id),
+ impl_vis,
+ tcx,
+ )
} else {
impl_vis
};
self.check_assoc_item(
- impl_item_ref.id.def_id,
+ impl_item_ref.id.owner_id.def_id,
impl_item_ref.kind,
impl_item_vis,
);
@@ -2007,7 +2048,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> {
pub fn provide(providers: &mut Providers) {
*providers = Providers {
visibility,
- privacy_access_levels,
+ effective_visibilities,
check_private_in_public,
check_mod_privacy,
..*providers
@@ -2040,7 +2081,7 @@ fn local_visibility(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Visibility {
// Visibilities of trait impl items are inherited from their traits
// and are not filled in resolve.
Node::ImplItem(impl_item) => {
- match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(hir_id)) {
+ match tcx.hir().get_by_def_id(tcx.hir().get_parent_item(hir_id).def_id) {
Node::Item(hir::Item {
kind: hir::ItemKind::Impl(hir::Impl { of_trait: Some(tr), .. }),
..
@@ -2079,14 +2120,14 @@ fn check_mod_privacy(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
intravisit::walk_mod(&mut visitor, module, hir_id);
}
-fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
+fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
// 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 {
tcx,
- access_levels: tcx.resolutions(()).access_levels.clone(),
+ effective_visibilities: tcx.resolutions(()).effective_visibilities.clone(),
macro_reachable: Default::default(),
- prev_level: Some(AccessLevel::Public),
+ prev_level: Some(Level::Direct),
changed: false,
};
@@ -2099,18 +2140,19 @@ fn privacy_access_levels(tcx: TyCtxt<'_>, (): ()) -> &AccessLevels {
}
}
- let mut check_visitor = TestReachabilityVisitor { tcx, access_levels: &visitor.access_levels };
+ let mut check_visitor =
+ TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };
tcx.hir().visit_all_item_likes_in_crate(&mut check_visitor);
- tcx.arena.alloc(visitor.access_levels)
+ tcx.arena.alloc(visitor.effective_visibilities)
}
fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) {
- let access_levels = tcx.privacy_access_levels(());
+ let effective_visibilities = tcx.effective_visibilities(());
let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
tcx,
- access_levels,
+ effective_visibilities,
in_variant: false,
old_error_set: Default::default(),
};