diff options
Diffstat (limited to 'compiler/rustc_privacy')
-rw-r--r-- | compiler/rustc_privacy/Cargo.toml | 2 | ||||
-rw-r--r-- | compiler/rustc_privacy/src/errors.rs | 42 | ||||
-rw-r--r-- | compiler/rustc_privacy/src/lib.rs | 342 |
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(), }; |