From 8b1c424b6d1cb001907e0fc0401e5242e297a83e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 16 Dec 2018 16:18:45 +0300 Subject: [PATCH 1/2] privacy: Use common `DefId` visiting infra for all privacy visitors --- src/librustc/hir/mod.rs | 9 + src/librustc_privacy/lib.rs | 911 ++++++++---------- src/libstd/sys/windows/handle.rs | 5 - src/libstd/sys/windows/stdio.rs | 5 - src/test/ui/error-codes/E0445.rs | 3 - src/test/ui/error-codes/E0445.stderr | 4 +- src/test/ui/impl-trait/issue-49376.rs | 4 +- src/test/ui/issues/issue-18389.stderr | 3 + .../ui/privacy/private-in-public-expr-pat.rs | 13 + .../private-in-public-non-principal-2.rs | 13 + .../private-in-public-non-principal-2.stderr | 8 + .../private-in-public-non-principal.rs | 20 + .../private-in-public-non-principal.stderr | 24 + src/test/ui/privacy/private-in-public-warn.rs | 9 + .../ui/privacy/private-in-public-warn.stderr | 21 +- src/test/ui/privacy/private-in-public.rs | 4 +- src/test/ui/privacy/private-in-public.stderr | 42 +- 17 files changed, 565 insertions(+), 533 deletions(-) create mode 100644 src/test/ui/privacy/private-in-public-expr-pat.rs create mode 100644 src/test/ui/privacy/private-in-public-non-principal-2.rs create mode 100644 src/test/ui/privacy/private-in-public-non-principal-2.stderr create mode 100644 src/test/ui/privacy/private-in-public-non-principal.rs create mode 100644 src/test/ui/privacy/private-in-public-non-principal.stderr diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index e6fa079207e59..7e87171a5edf7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -2090,6 +2090,15 @@ impl VisibilityKind { VisibilityKind::Restricted { .. } => true, } } + + pub fn descr(&self) -> &'static str { + match *self { + VisibilityKind::Public => "public", + VisibilityKind::Inherited => "private", + VisibilityKind::Crate(..) => "crate-visible", + VisibilityKind::Restricted { .. } => "restricted", + } + } } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 67b6b2d04506d..0cd8c9da57e29 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -20,22 +20,260 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::itemlikevisit::DeepVisitor; use rustc::lint; use rustc::middle::privacy::{AccessLevel, AccessLevels}; -use rustc::ty::{self, TyCtxt, Ty, TypeFoldable, GenericParamDefKind}; +use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind}; use rustc::ty::fold::TypeVisitor; use rustc::ty::query::Providers; -use rustc::ty::subst::UnpackedKind; use rustc::util::nodemap::NodeSet; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use syntax::ast::{self, CRATE_NODE_ID, Ident}; +use syntax::attr; use syntax::symbol::keywords; use syntax_pos::Span; -use std::cmp; +use std::{cmp, fmt}; use std::mem::replace; +use std::marker::PhantomData; mod diagnostics; +//////////////////////////////////////////////////////////////////////////////// +/// Generic infrastructure used to implement specific visitors below. +//////////////////////////////////////////////////////////////////////////////// + +/// Implemented to visit all `DefId`s in a type. +/// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them. +trait DefIdVisitor<'a, 'tcx: 'a> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>; + fn recurse_into_assoc_tys(&self) -> bool { true } + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool; + + /// Not overridden, but used to actually visit types and traits. + fn skeleton(&mut self) -> DefIdVisitorSkeleton<'_, 'a, 'tcx, Self> { + DefIdVisitorSkeleton { + def_id_visitor: self, + visited_opaque_tys: Default::default(), + dummy: Default::default(), + } + } + fn visit(&mut self, ty_fragment: impl TypeFoldable<'tcx>) -> bool { + ty_fragment.visit_with(&mut self.skeleton()) + } + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { + self.skeleton().visit_trait(trait_ref) + } + fn visit_predicates(&mut self, predicates: Lrc>) -> bool { + self.skeleton().visit_predicates(predicates) + } +} + +struct DefIdVisitorSkeleton<'v, 'a, 'tcx, V> + where V: DefIdVisitor<'a, 'tcx> + ?Sized +{ + def_id_visitor: &'v mut V, + visited_opaque_tys: FxHashSet, + dummy: PhantomData>, +} + +impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> + where V: DefIdVisitor<'a, 'tcx> + ?Sized +{ + fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { + self.def_id_visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref) || + trait_ref.visit_with(self) + } + + fn visit_predicates(&mut self, predicates: Lrc>) -> bool { + for (predicate, _) in &predicates.predicates { + let trait_ref = match predicate { + ty::Predicate::Trait(poly_predicate) => { + poly_predicate.skip_binder().trait_ref + } + ty::Predicate::Projection(poly_predicate) => { + if poly_predicate.skip_binder().ty.visit_with(self) { + return true; + } + poly_predicate.skip_binder().projection_ty.trait_ref(self.def_id_visitor.tcx()) + } + ty::Predicate::TypeOutlives(poly_predicate) => { + if poly_predicate.skip_binder().0.visit_with(self) { + return true; + } + continue; + } + ty::Predicate::RegionOutlives(..) => continue, + _ => bug!("unexpected predicate: {:?}", predicate), + }; + if self.visit_trait(trait_ref) { + return true; + } + } + false + } +} + +impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> + where V: DefIdVisitor<'a, 'tcx> + ?Sized +{ + fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { + let tcx = self.def_id_visitor.tcx(); + match ty.sty { + ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | + ty::Foreign(def_id) | + ty::FnDef(def_id, ..) | + ty::Closure(def_id, ..) | + ty::Generator(def_id, ..) => { + if self.def_id_visitor.visit_def_id(def_id, "type", ty) { + return true; + } + // Default type visitor doesn't visit fn signatures. + if let ty::FnDef(..) = ty.sty { + if tcx.fn_sig(def_id).visit_with(self) { + return true; + } + } + // Inherent static methods don't have self type in substs, + // we have to check it additionally. + if let Some(assoc_item) = tcx.opt_associated_item(def_id) { + if let ty::ImplContainer(impl_def_id) = assoc_item.container { + if tcx.type_of(impl_def_id).visit_with(self) { + return true; + } + } + } + } + ty::Projection(proj) | ty::UnnormalizedProjection(proj) => { + if !self.def_id_visitor.recurse_into_assoc_tys() { + // Visitors searching for minimal visibility/reachability want to + // conservatively approximate associated types like `::Alias` + // as visible/reachable even if both `Type` and `Trait` are private. + // Ideally, associated types should be substituted in the same way as + // free type aliases, but this isn't done yet. + return false; + } + // This will also visit substs, so we don't need to recurse. + return self.visit_trait(proj.trait_ref(tcx)); + } + ty::Dynamic(predicates, ..) => { + for predicate in *predicates.skip_binder() { + let def_id = match *predicate { + ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, + ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx).def_id, + ty::ExistentialPredicate::AutoTrait(def_id) => def_id, + }; + if self.def_id_visitor.visit_def_id(def_id, "type", ty) { + return true; + } + } + } + ty::Opaque(def_id, ..) => { + // Skip repeated `Opaque`s to avoid infinite recursion. + if self.visited_opaque_tys.insert(def_id) { + if self.visit_predicates(tcx.predicates_of(def_id)) { + return true; + } + } + } + // 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(..) | ty::FnPtr(..) | + ty::Param(..) | ty::Error | ty::GeneratorWitness(..) => {} + ty::Bound(..) | ty::Placeholder(..) | ty::Infer(..) => + bug!("unexpected type: {:?}", ty), + } + + ty.super_visit_with(self) + } +} + +fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) + -> (ty::Visibility, Span, &'static str) { + match tcx.hir().as_local_node_id(def_id) { + Some(node_id) => { + let vis = match tcx.hir().get(node_id) { + Node::Item(item) => &item.vis, + Node::ForeignItem(foreign_item) => &foreign_item.vis, + Node::TraitItem(..) | Node::Variant(..) => { + return def_id_visibility(tcx, tcx.hir().get_parent_did(node_id)); + } + Node::ImplItem(impl_item) => { + match tcx.hir().get(tcx.hir().get_parent(node_id)) { + Node::Item(item) => match &item.node { + hir::ItemKind::Impl(.., None, _, _) => &impl_item.vis, + hir::ItemKind::Impl(.., Some(trait_ref), _, _) + => return def_id_visibility(tcx, trait_ref.path.def.def_id()), + kind => bug!("unexpected item kind: {:?}", kind), + } + node => bug!("unexpected node kind: {:?}", node), + } + } + Node::StructCtor(vdata) => { + let struct_node_id = tcx.hir().get_parent(node_id); + let item = match tcx.hir().get(struct_node_id) { + Node::Item(item) => item, + node => bug!("unexpected node kind: {:?}", node), + }; + let (mut ctor_vis, mut span, mut descr) = + (ty::Visibility::from_hir(&item.vis, struct_node_id, tcx), + item.vis.span, item.vis.node.descr()); + for field in vdata.fields() { + let field_vis = ty::Visibility::from_hir(&field.vis, node_id, tcx); + if ctor_vis.is_at_least(field_vis, tcx) { + ctor_vis = field_vis; + span = field.vis.span; + descr = field.vis.node.descr(); + } + } + + // If the structure is marked as non_exhaustive then lower the + // visibility to within the crate. + if ctor_vis == ty::Visibility::Public { + let adt_def = tcx.adt_def(tcx.hir().get_parent_did(node_id)); + if adt_def.non_enum_variant().is_field_list_non_exhaustive() { + ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); + span = attr::find_by_name(&item.attrs, "non_exhaustive").unwrap().span; + descr = "crate-visible"; + } + } + + return (ctor_vis, span, descr); + } + Node::Expr(expr) => { + return (ty::Visibility::Restricted(tcx.hir().get_module_parent(expr.id)), + expr.span, "private") + } + node => bug!("unexpected node kind: {:?}", node) + }; + (ty::Visibility::from_hir(vis, node_id, tcx), vis.span, vis.node.descr()) + } + None => (tcx.visibility(def_id), tcx.def_span(def_id), "private"), + } +} + +// Set the correct `TypeckTables` for the given `item_id` (or an empty table if +// there is no `TypeckTables` for the item). +fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + item_id: ast::NodeId, + tables: &mut &'a ty::TypeckTables<'tcx>, + empty_tables: &'a ty::TypeckTables<'tcx>) + -> &'a ty::TypeckTables<'tcx> { + let def_id = tcx.hir().local_def_id(item_id); + + if tcx.has_typeck_tables(def_id) { + replace(tables, tcx.typeck_tables_of(def_id)) + } else { + replace(tables, empty_tables) + } +} + +fn min<'a, 'tcx>(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::Visibility { + if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } +} + //////////////////////////////////////////////////////////////////////////////// /// Visitor used to determine if pub(restricted) is used anywhere in the crate. /// @@ -56,6 +294,57 @@ impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> { } } +//////////////////////////////////////////////////////////////////////////////// +/// Visitor used to determine impl visibility and reachability. +//////////////////////////////////////////////////////////////////////////////// + +struct FindMin<'a, 'tcx, M: Min> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + access_levels: &'a AccessLevels, + min: M, +} + +trait Min: Sized { + const MAX: Self; + fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self; +} +impl Min for ty::Visibility { + const MAX: Self = ty::Visibility::Public; + fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { + min(def_id_visibility(find.tcx, def_id).0, find.min, find.tcx) + } +} +impl Min for Option { + const MAX: Self = Some(AccessLevel::Public); + fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { + cmp::min(if let Some(node_id) = find.tcx.hir().as_local_node_id(def_id) { + find.access_levels.map.get(&node_id).cloned() + } else { + Self::MAX + }, find.min) + } +} + +impl<'a, 'tcx, M: Min> DefIdVisitor<'a, 'tcx> for FindMin<'a, 'tcx, M> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn recurse_into_assoc_tys(&self) -> bool { false } + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { + self.min = M::new_min(self, def_id); + false + } +} + +fn impl_min<'a, 'tcx, M: Min>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &'a AccessLevels, + node_id: ast::NodeId) -> M { + let mut find = FindMin { tcx, access_levels, min: M::MAX }; + let def_id = tcx.hir().local_def_id(node_id); + find.visit(tcx.type_of(def_id)); + if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { + find.visit_trait(trait_ref); + } + find.min +} + //////////////////////////////////////////////////////////////////////////////// /// The embargo visitor, used to determine the exports of the ast //////////////////////////////////////////////////////////////////////////////// @@ -78,30 +367,6 @@ struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> { } impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { - fn item_ty_level(&self, item_def_id: DefId) -> Option { - let ty_def_id = match self.tcx.type_of(item_def_id).sty { - ty::Adt(adt, _) => adt.did, - ty::Foreign(did) => did, - ty::Dynamic(ref obj, ..) => obj.principal().def_id(), - ty::Projection(ref proj) => proj.trait_ref(self.tcx).def_id, - _ => return Some(AccessLevel::Public) - }; - if let Some(node_id) = self.tcx.hir().as_local_node_id(ty_def_id) { - self.get(node_id) - } else { - Some(AccessLevel::Public) - } - } - - fn impl_trait_level(&self, impl_def_id: DefId) -> Option { - if let Some(trait_ref) = self.tcx.impl_trait_ref(impl_def_id) { - if let Some(node_id) = self.tcx.hir().as_local_node_id(trait_ref.def_id) { - return self.get(node_id); - } - } - Some(AccessLevel::Public) - } - fn get(&self, id: ast::NodeId) -> Option { self.access_levels.map.get(&id).cloned() } @@ -119,10 +384,10 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { } } - fn reach<'b>(&'b mut self, item_id: ast::NodeId) - -> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { + fn reach(&mut self, item_id: ast::NodeId, access_level: Option) + -> ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> { ReachEverythingInTheInterfaceVisitor { - access_level: self.prev_level.map(|l| l.min(AccessLevel::Reachable)), + access_level: cmp::min(access_level, Some(AccessLevel::Reachable)), item_def_id: self.tcx.hir().local_def_id(item_id), ev: self, } @@ -138,15 +403,10 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { let inherited_item_level = match item.node { - // Impls inherit level from their types and traits. - hir::ItemKind::Impl(..) => { - let def_id = self.tcx.hir().local_def_id(item.id); - cmp::min(self.item_ty_level(def_id), self.impl_trait_level(def_id)) - } + hir::ItemKind::Impl(..) => + impl_min::>(self.tcx, &self.access_levels, item.id), // Foreign modules inherit level from parents. - hir::ItemKind::ForeignMod(..) => { - self.prev_level - } + hir::ItemKind::ForeignMod(..) => self.prev_level, // Other `pub` items inherit levels from parents. hir::ItemKind::Const(..) | hir::ItemKind::Enum(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Mod(..) | @@ -171,18 +431,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - hir::ItemKind::Impl(.., None, _, ref impl_item_refs) => { + hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { for impl_item_ref in impl_item_refs { - if impl_item_ref.vis.node.is_pub() { + if trait_ref.is_some() || impl_item_ref.vis.node.is_pub() { self.update(impl_item_ref.id.node_id, item_level); } } } - hir::ItemKind::Impl(.., Some(_), _, ref impl_item_refs) => { - for impl_item_ref in impl_item_refs { - self.update(impl_item_ref.id.node_id, item_level); - } - } hir::ItemKind::Trait(.., ref trait_item_refs) => { for trait_item_ref in trait_item_refs { self.update(trait_item_ref.id.node_id, item_level); @@ -205,15 +460,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } } - // Impl trait return types mark their parent function. - // It (and its children) are revisited if the change applies. - hir::ItemKind::Existential(ref ty_data) => { - if let Some(impl_trait_fn) = ty_data.impl_trait_fn { - if let Some(node_id) = self.tcx.hir().as_local_node_id(impl_trait_fn) { - self.update(node_id, Some(AccessLevel::ReachableFromImplTrait)); - } - } - } + hir::ItemKind::Existential(..) | hir::ItemKind::Use(..) | hir::ItemKind::Static(..) | hir::ItemKind::Const(..) | @@ -225,10 +472,6 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::ExternCrate(..) => {} } - // Store this node's access level here to propagate the correct - // reachability level through interfaces and children. - let orig_level = replace(&mut self.prev_level, item_level); - // Mark all items in interfaces of reachable items as reachable. match item.node { // The interface is empty. @@ -239,26 +482,26 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::Use(..) => {} // The interface is empty. hir::ItemKind::GlobalAsm(..) => {} - hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => { - if item_level.is_some() { - // Reach the (potentially private) type and the API being exposed. - self.reach(item.id).ty().predicates(); - } + hir::ItemKind::Existential(..) => { + // 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.id, exist_level).generics().predicates().ty(); } // Visit everything. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | - hir::ItemKind::Existential(..) | hir::ItemKind::Fn(..) | hir::ItemKind::Ty(..) => { if item_level.is_some() { - self.reach(item.id).generics().predicates().ty(); + self.reach(item.id, item_level).generics().predicates().ty(); } } hir::ItemKind::Trait(.., ref trait_item_refs) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); for trait_item_ref in trait_item_refs { - let mut reach = self.reach(trait_item_ref.id.node_id); + let mut reach = self.reach(trait_item_ref.id.node_id, item_level); reach.generics().predicates(); if trait_item_ref.kind == hir::AssociatedItemKind::Type && @@ -272,18 +515,19 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } hir::ItemKind::TraitAlias(..) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); } } // Visit everything except for private impl items. - hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { + hir::ItemKind::Impl(.., ref impl_item_refs) => { if item_level.is_some() { - self.reach(item.id).generics().predicates().impl_trait_ref(); + self.reach(item.id, item_level).generics().predicates(); for impl_item_ref in impl_item_refs { - let id = impl_item_ref.id.node_id; - if trait_ref.is_some() || self.get(id).is_some() { - self.reach(id).generics().predicates().ty(); + let impl_item_level = self.get(impl_item_ref.id.node_id); + if impl_item_level.is_some() { + self.reach(impl_item_ref.id.node_id, impl_item_level) + .generics().predicates().ty(); } } } @@ -292,24 +536,27 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Visit everything, but enum variants have their own levels. hir::ItemKind::Enum(ref def, _) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); } for variant in &def.variants { - if self.get(variant.node.data.id()).is_some() { + let variant_level = self.get(variant.node.data.id()); + if variant_level.is_some() { for field in variant.node.data.fields() { - self.reach(field.id).ty(); + self.reach(field.id, variant_level).ty(); } // Corner case: if the variant is reachable, but its // enum is not, make the enum reachable as well. - self.update(item.id, Some(AccessLevel::Reachable)); + self.update(item.id, variant_level); } } } // Visit everything, but foreign items have their own levels. hir::ItemKind::ForeignMod(ref foreign_mod) => { for foreign_item in &foreign_mod.items { - if self.get(foreign_item.id).is_some() { - self.reach(foreign_item.id).generics().predicates().ty(); + let foreign_item_level = self.get(foreign_item.id); + if foreign_item_level.is_some() { + self.reach(foreign_item.id, foreign_item_level) + .generics().predicates().ty(); } } } @@ -317,29 +564,28 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) => { if item_level.is_some() { - self.reach(item.id).generics().predicates(); + self.reach(item.id, item_level).generics().predicates(); for field in struct_def.fields() { - if self.get(field.id).is_some() { - self.reach(field.id).ty(); + let field_level = self.get(field.id); + if field_level.is_some() { + self.reach(field.id, field_level).ty(); } } } } } + let orig_level = replace(&mut self.prev_level, item_level); intravisit::walk_item(self, item); - self.prev_level = orig_level; } fn visit_block(&mut self, b: &'tcx hir::Block) { - let orig_level = replace(&mut self.prev_level, None); - // Blocks can have public items, for example impls, but they always // start as completely private regardless of publicity of a function, // constant, type, field, etc., in which this block resides. + let orig_level = replace(&mut self.prev_level, None); intravisit::walk_block(self, b); - self.prev_level = orig_level; } @@ -410,13 +656,13 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } -impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { +impl<'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> { fn generics(&mut self) -> &mut Self { for param in &self.ev.tcx.generics_of(self.item_def_id).params { match param.kind { GenericParamDefKind::Type { has_default, .. } => { if has_default { - self.ev.tcx.type_of(param.def_id).visit_with(self); + self.visit(self.ev.tcx.type_of(param.def_id)); } } GenericParamDefKind::Lifetime => {} @@ -426,73 +672,23 @@ impl<'b, 'a, 'tcx> ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { } fn predicates(&mut self) -> &mut Self { - let predicates = self.ev.tcx.predicates_of(self.item_def_id); - for (predicate, _) in &predicates.predicates { - predicate.visit_with(self); - match predicate { - &ty::Predicate::Trait(poly_predicate) => { - self.check_trait_ref(poly_predicate.skip_binder().trait_ref); - }, - &ty::Predicate::Projection(poly_predicate) => { - let tcx = self.ev.tcx; - self.check_trait_ref( - poly_predicate.skip_binder().projection_ty.trait_ref(tcx) - ); - }, - _ => (), - }; - } + self.visit_predicates(self.ev.tcx.predicates_of(self.item_def_id)); self } fn ty(&mut self) -> &mut Self { - let ty = self.ev.tcx.type_of(self.item_def_id); - ty.visit_with(self); - if let ty::FnDef(def_id, _) = ty.sty { - if def_id == self.item_def_id { - self.ev.tcx.fn_sig(def_id).visit_with(self); - } - } - self - } - - fn impl_trait_ref(&mut self) -> &mut Self { - if let Some(impl_trait_ref) = self.ev.tcx.impl_trait_ref(self.item_def_id) { - self.check_trait_ref(impl_trait_ref); - impl_trait_ref.super_visit_with(self); - } + self.visit(self.ev.tcx.type_of(self.item_def_id)); self } - - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { - if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(trait_ref.def_id) { - let item = self.ev.tcx.hir().expect_item(node_id); - self.ev.update(item.id, self.access_level); - } - } } -impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b, 'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - let ty_def_id = match ty.sty { - ty::Adt(adt, _) => Some(adt.did), - ty::Foreign(did) => Some(did), - ty::Dynamic(ref obj, ..) => Some(obj.principal().def_id()), - ty::Projection(ref proj) => Some(proj.item_def_id), - ty::FnDef(def_id, ..) | - ty::Closure(def_id, ..) | - ty::Generator(def_id, ..) | - ty::Opaque(def_id, _) => Some(def_id), - _ => None - }; - - if let Some(def_id) = ty_def_id { - if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(def_id) { - self.ev.update(node_id, self.access_level); - } +impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.ev.tcx } + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { + if let Some(node_id) = self.ev.tcx.hir().as_local_node_id(def_id) { + self.ev.update(node_id, self.access_level); } - - ty.super_visit_with(self) + false } } @@ -528,22 +724,6 @@ impl<'a, 'tcx> NamePrivacyVisitor<'a, 'tcx> { } } -// Set the correct `TypeckTables` for the given `item_id` (or an empty table if -// there is no `TypeckTables` for the item). -fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item_id: ast::NodeId, - tables: &mut &'a ty::TypeckTables<'tcx>, - empty_tables: &'a ty::TypeckTables<'tcx>) - -> &'a ty::TypeckTables<'tcx> { - let def_id = tcx.hir().local_def_id(item_id); - - if tcx.has_typeck_tables(def_id) { - replace(tables, tcx.typeck_tables_of(def_id)) - } else { - replace(tables, empty_tables) - } -} - impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. @@ -644,73 +824,22 @@ struct TypePrivacyVisitor<'a, 'tcx: 'a> { in_body: bool, span: Span, empty_tables: &'a ty::TypeckTables<'tcx>, - visited_opaque_tys: FxHashSet } impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { - fn def_id_visibility(&self, did: DefId) -> ty::Visibility { - match self.tcx.hir().as_local_node_id(did) { - Some(node_id) => { - let vis = match self.tcx.hir().get(node_id) { - Node::Item(item) => &item.vis, - Node::ForeignItem(foreign_item) => &foreign_item.vis, - Node::ImplItem(impl_item) => &impl_item.vis, - Node::TraitItem(..) | - Node::Variant(..) => { - return self.def_id_visibility(self.tcx.hir().get_parent_did(node_id)); - } - Node::StructCtor(vdata) => { - let struct_node_id = self.tcx.hir().get_parent(node_id); - let struct_vis = match self.tcx.hir().get(struct_node_id) { - Node::Item(item) => &item.vis, - node => bug!("unexpected node kind: {:?}", node), - }; - let mut ctor_vis - = ty::Visibility::from_hir(struct_vis, struct_node_id, self.tcx); - for field in vdata.fields() { - let field_vis = ty::Visibility::from_hir(&field.vis, node_id, self.tcx); - if ctor_vis.is_at_least(field_vis, self.tcx) { - ctor_vis = field_vis; - } - } - - // If the structure is marked as non_exhaustive then lower the - // visibility to within the crate. - let struct_def_id = self.tcx.hir().get_parent_did(node_id); - let adt_def = self.tcx.adt_def(struct_def_id); - if adt_def.non_enum_variant().is_field_list_non_exhaustive() - && ctor_vis == ty::Visibility::Public - { - ctor_vis = ty::Visibility::Restricted( - DefId::local(CRATE_DEF_INDEX)); - } - - return ctor_vis; - } - node => bug!("unexpected node kind: {:?}", node) - }; - ty::Visibility::from_hir(vis, node_id, self.tcx) - } - None => self.tcx.visibility(did), - } - } - fn item_is_accessible(&self, did: DefId) -> bool { - self.def_id_visibility(did).is_accessible_from(self.current_item, self.tcx) + def_id_visibility(self.tcx, did).0.is_accessible_from(self.current_item, self.tcx) } // Take node-id of an expression or pattern and check its type for privacy. fn check_expr_pat_type(&mut self, id: hir::HirId, span: Span) -> bool { self.span = span; - if self.tables.node_id_to_type(id).visit_with(self) { - return true; - } - if self.tables.node_substs(id).visit_with(self) { + if self.visit(self.tables.node_id_to_type(id)) || self.visit(self.tables.node_substs(id)) { return true; } if let Some(adjustments) = self.tables.adjustments().get(id) { for adjustment in adjustments { - if adjustment.target.visit_with(self) { + if self.visit(adjustment.target) { return true; } } @@ -718,14 +847,12 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> { false } - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) -> bool { - if !self.item_is_accessible(trait_ref.def_id) { - let msg = format!("trait `{}` is private", trait_ref); - self.tcx.sess.span_err(self.span, &msg); - return true; + 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 { + self.tcx.sess.span_err(self.span, &format!("{} `{}` is private", kind, descr)); } - - trait_ref.super_visit_with(self) + is_error } } @@ -749,14 +876,14 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { self.span = hir_ty.span; if self.in_body { // Types in bodies. - if self.tables.node_id_to_type(hir_ty.hir_id).visit_with(self) { + if self.visit(self.tables.node_id_to_type(hir_ty.hir_id)) { return; } } else { // 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 rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty).visit_with(self) { + if self.visit(rustc_typeck::hir_ty_to_ty(self.tcx, hir_ty)) { return; } } @@ -771,12 +898,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // The traits' privacy in bodies is already checked as a part of trait object types. let (principal, projections) = rustc_typeck::hir_trait_to_predicates(self.tcx, trait_ref); - if self.check_trait_ref(*principal.skip_binder()) { + if self.visit_trait(*principal.skip_binder()) { return; } for (poly_predicate, _) in projections { let tcx = self.tcx; - if self.check_trait_ref(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) { + if self.visit(poly_predicate.skip_binder().ty) || + self.visit_trait(poly_predicate.skip_binder().projection_ty.trait_ref(tcx)) { return; } } @@ -802,8 +930,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Method calls have to be checked specially. self.span = span; if let Some(def) = self.tables.type_dependent_defs().get(expr.hir_id) { - let def_id = def.def_id(); - if self.tcx.type_of(def_id).visit_with(self) { + if self.visit(self.tcx.type_of(def.def_id())) { return; } } else { @@ -827,7 +954,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { let def = match *qpath { hir::QPath::Resolved(_, ref path) => match path.def { Def::Method(..) | Def::AssociatedConst(..) | - Def::AssociatedTy(..) | Def::Static(..) => Some(path.def), + Def::AssociatedTy(..) | Def::AssociatedExistential(..) | + Def::Static(..) => Some(path.def), _ => None, } hir::QPath::TypeRelative(..) => { @@ -874,13 +1002,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item) { - let orig_current_item = self.current_item; - let orig_tables = update_tables(self.tcx, - item.id, - &mut self.tables, - self.empty_tables); + let orig_current_item = + replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id)); let orig_in_body = replace(&mut self.in_body, false); - self.current_item = self.tcx.hir().local_def_id(item.id); + let orig_tables = update_tables(self.tcx, item.id, &mut self.tables, self.empty_tables); intravisit::walk_item(self, item); self.tables = orig_tables; self.in_body = orig_in_body; @@ -900,96 +1025,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } } -impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - match ty.sty { - ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | - ty::FnDef(def_id, ..) | - ty::Foreign(def_id) => { - if !self.item_is_accessible(def_id) { - let msg = format!("type `{}` is private", ty); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - if let ty::FnDef(..) = ty.sty { - if self.tcx.fn_sig(def_id).visit_with(self) { - return true; - } - } - // Inherent static methods don't have self type in substs, - // we have to check it additionally. - if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) { - if let ty::ImplContainer(impl_def_id) = assoc_item.container { - if self.tcx.type_of(impl_def_id).visit_with(self) { - return true; - } - } - } - } - ty::Dynamic(ref predicates, ..) => { - let is_private = predicates.skip_binder().iter().any(|predicate| { - let def_id = match *predicate { - ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, - ty::ExistentialPredicate::Projection(proj) => - proj.trait_ref(self.tcx).def_id, - ty::ExistentialPredicate::AutoTrait(def_id) => def_id, - }; - !self.item_is_accessible(def_id) - }); - if is_private { - let msg = format!("type `{}` is private", ty); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - } - ty::Projection(ref proj) => { - let tcx = self.tcx; - if self.check_trait_ref(proj.trait_ref(tcx)) { - return true; - } - } - ty::Opaque(def_id, ..) => { - for (predicate, _) in &self.tcx.predicates_of(def_id).predicates { - let trait_ref = match *predicate { - ty::Predicate::Trait(ref poly_trait_predicate) => { - Some(poly_trait_predicate.skip_binder().trait_ref) - } - ty::Predicate::Projection(ref poly_projection_predicate) => { - if poly_projection_predicate.skip_binder().ty.visit_with(self) { - return true; - } - Some(poly_projection_predicate.skip_binder() - .projection_ty.trait_ref(self.tcx)) - } - ty::Predicate::TypeOutlives(..) | ty::Predicate::RegionOutlives(..) => None, - _ => bug!("unexpected predicate: {:?}", predicate), - }; - if let Some(trait_ref) = trait_ref { - if !self.item_is_accessible(trait_ref.def_id) { - let msg = format!("trait `{}` is private", trait_ref); - self.tcx.sess.span_err(self.span, &msg); - return true; - } - for subst in trait_ref.substs.iter() { - // Skip repeated `Opaque`s to avoid infinite recursion. - if let UnpackedKind::Type(ty) = subst.unpack() { - if let ty::Opaque(def_id, ..) = ty.sty { - if !self.visited_opaque_tys.insert(def_id) { - continue; - } - } - } - if subst.visit_with(self) { - return true; - } - } - } - } - } - _ => {} - } - - ty.super_visit_with(self) +impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for TypePrivacyVisitor<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + self.check_def_id(def_id, kind, descr) } } @@ -1283,13 +1322,13 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } for predicate in &generics.where_clause.predicates { match predicate { - &hir::WherePredicate::BoundPredicate(ref bound_pred) => { + hir::WherePredicate::BoundPredicate(bound_pred) => { for bound in bound_pred.bounds.iter() { self.check_generic_bound(bound) } } - &hir::WherePredicate::RegionPredicate(_) => {} - &hir::WherePredicate::EqPredicate(ref eq_pred) => { + hir::WherePredicate::RegionPredicate(_) => {} + hir::WherePredicate::EqPredicate(eq_pred) => { self.visit_ty(&eq_pred.rhs_ty); } } @@ -1349,8 +1388,6 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> { span: Span, /// The visitor checks that each component type is at least this visible. required_visibility: ty::Visibility, - /// The visibility of the least visible component that has been visited. - min_visibility: ty::Visibility, has_pub_restricted: bool, has_old_errors: bool, in_assoc_ty: bool, @@ -1362,7 +1399,7 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { match param.kind { GenericParamDefKind::Type { has_default, .. } => { if has_default { - self.tcx.type_of(param.def_id).visit_with(self); + self.visit(self.tcx.type_of(param.def_id)); } } GenericParamDefKind::Lifetime => {} @@ -1378,132 +1415,47 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { // consider the ones that the user wrote. This is important // for the inferred outlives rules; see // `src/test/ui/rfc-2093-infer-outlives/privacy.rs`. - let predicates = self.tcx.explicit_predicates_of(self.item_def_id); - for (predicate, _) in &predicates.predicates { - predicate.visit_with(self); - match predicate { - &ty::Predicate::Trait(poly_predicate) => { - self.check_trait_ref(poly_predicate.skip_binder().trait_ref); - }, - &ty::Predicate::Projection(poly_predicate) => { - let tcx = self.tcx; - self.check_trait_ref( - poly_predicate.skip_binder().projection_ty.trait_ref(tcx) - ); - }, - _ => (), - }; - } + self.visit_predicates(self.tcx.explicit_predicates_of(self.item_def_id)); self } fn ty(&mut self) -> &mut Self { - let ty = self.tcx.type_of(self.item_def_id); - ty.visit_with(self); - if let ty::FnDef(def_id, _) = ty.sty { - if def_id == self.item_def_id { - self.tcx.fn_sig(def_id).visit_with(self); - } - } + self.visit(self.tcx.type_of(self.item_def_id)); self } - fn impl_trait_ref(&mut self) -> &mut Self { - if let Some(impl_trait_ref) = self.tcx.impl_trait_ref(self.item_def_id) { - self.check_trait_ref(impl_trait_ref); - impl_trait_ref.super_visit_with(self); - } - self - } + fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + let node_id = match self.tcx.hir().as_local_node_id(def_id) { + Some(node_id) => node_id, + None => return false, + }; - fn check_trait_ref(&mut self, trait_ref: ty::TraitRef<'tcx>) { - // Non-local means public (private items can't leave their crate, modulo bugs). - if let Some(node_id) = self.tcx.hir().as_local_node_id(trait_ref.def_id) { - let item = self.tcx.hir().expect_item(node_id); - let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx); - if !vis.is_at_least(self.min_visibility, self.tcx) { - self.min_visibility = vis; - } - if !vis.is_at_least(self.required_visibility, self.tcx) { - if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { - struct_span_err!(self.tcx.sess, self.span, E0445, - "private trait `{}` in public interface", trait_ref) - .span_label(self.span, format!( - "can't leak private trait")) - .emit(); + let (vis, vis_span, vis_descr) = def_id_visibility(self.tcx, def_id); + if !vis.is_at_least(self.required_visibility, self.tcx) { + let msg = format!("{} {} `{}` in public interface", vis_descr, kind, descr); + if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { + let mut err = if kind == "trait" { + struct_span_err!(self.tcx.sess, self.span, E0445, "{}", msg) } else { - self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - &format!("private trait `{}` in public \ - interface (error E0445)", trait_ref)); - } + struct_span_err!(self.tcx.sess, self.span, E0446, "{}", msg) + }; + err.span_label(self.span, format!("can't leak {} {}", vis_descr, kind)); + err.span_label(vis_span, format!("`{}` declared as {}", descr, vis_descr)); + err.emit(); + } else { + let err_code = if kind == "trait" { "E0445" } else { "E0446" }; + self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, node_id, self.span, + &format!("{} (error {})", msg, err_code)); } } + false } } -impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { - fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { - let ty_def_id = match ty.sty { - ty::Adt(adt, _) => Some(adt.did), - ty::Foreign(did) => Some(did), - ty::Dynamic(ref obj, ..) => Some(obj.principal().def_id()), - ty::Projection(ref proj) => { - if self.required_visibility == ty::Visibility::Invisible { - // Conservatively approximate the whole type alias as public without - // recursing into its components when determining impl publicity. - // For example, `impl ::Alias {...}` may be a public impl - // even if both `Type` and `Trait` are private. - // Ideally, associated types should be substituted in the same way as - // free type aliases, but this isn't done yet. - return false; - } - let trait_ref = proj.trait_ref(self.tcx); - Some(trait_ref.def_id) - } - _ => None - }; - - if let Some(def_id) = ty_def_id { - // Non-local means public (private items can't leave their crate, modulo bugs). - if let Some(node_id) = self.tcx.hir().as_local_node_id(def_id) { - let hir_vis = match self.tcx.hir().find(node_id) { - Some(Node::Item(item)) => &item.vis, - Some(Node::ForeignItem(item)) => &item.vis, - _ => bug!("expected item of foreign item"), - }; - - let vis = ty::Visibility::from_hir(hir_vis, node_id, self.tcx); - - if !vis.is_at_least(self.min_visibility, self.tcx) { - self.min_visibility = vis; - } - if !vis.is_at_least(self.required_visibility, self.tcx) { - let vis_adj = match hir_vis.node { - hir::VisibilityKind::Crate(_) => "crate-visible", - hir::VisibilityKind::Restricted { .. } => "restricted", - _ => "private" - }; - - if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty { - let mut err = struct_span_err!(self.tcx.sess, self.span, E0446, - "{} type `{}` in public interface", vis_adj, ty); - err.span_label(self.span, format!("can't leak {} type", vis_adj)); - err.span_label(hir_vis.span, format!("`{}` declared as {}", ty, vis_adj)); - err.emit(); - } else { - self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC, - node_id, - self.span, - &format!("{} type `{}` in public \ - interface (error E0446)", vis_adj, ty)); - } - } - } - } - - ty.super_visit_with(self) +impl<'a, 'tcx> DefIdVisitor<'a, 'tcx> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn visit_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool { + self.check_def_id(def_id, kind, descr) } } @@ -1511,7 +1463,6 @@ struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> { tcx: TyCtxt<'a, 'tcx, 'tcx>, has_pub_restricted: bool, old_error_set: &'a NodeSet, - inner_visibility: ty::Visibility, } impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { @@ -1544,7 +1495,6 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { tcx: self.tcx, item_def_id: self.tcx.hir().local_def_id(item_id), span: self.tcx.hir().span(item_id), - min_visibility: ty::Visibility::Public, required_visibility, has_pub_restricted: self.has_pub_restricted, has_old_errors, @@ -1560,10 +1510,6 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> fn visit_item(&mut self, item: &'tcx hir::Item) { let tcx = self.tcx; - let min = |vis1: ty::Visibility, vis2| { - if vis1.is_at_least(vis2, tcx) { vis2 } else { vis1 } - }; - let item_visibility = ty::Visibility::from_hir(&item.vis, item.id, tcx); match item.node { @@ -1575,23 +1521,10 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> hir::ItemKind::Use(..) => {} // No subitems. hir::ItemKind::GlobalAsm(..) => {} - hir::ItemKind::Existential(hir::ExistTy { impl_trait_fn: Some(_), .. }) => { - // Check the traits being exposed, as they're separate, - // e.g., `impl Iterator` has two predicates, - // `X: Iterator` and `::Item == T`, - // where `X` is the `impl Iterator` itself, - // stored in `predicates_of`, not in the `Ty` itself. - self.check(item.id, item_visibility).predicates(); - } // Subitems of these items have inherited publicity. hir::ItemKind::Const(..) | hir::ItemKind::Static(..) | hir::ItemKind::Fn(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::Ty(..) => { + hir::ItemKind::Existential(..) | hir::ItemKind::Ty(..) => { self.check(item.id, item_visibility).generics().predicates().ty(); - - // Recurse for e.g., `impl Trait` (see `visit_ty`). - self.inner_visibility = item_visibility; - intravisit::walk_item(self, item); } hir::ItemKind::Trait(.., ref trait_item_refs) => { self.check(item.id, item_visibility).generics().predicates(); @@ -1635,56 +1568,30 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> for field in struct_def.fields() { let field_visibility = ty::Visibility::from_hir(&field.vis, item.id, tcx); - self.check(field.id, min(item_visibility, field_visibility)).ty(); + self.check(field.id, min(item_visibility, field_visibility, tcx)).ty(); } } // An inherent impl is public when its type is public // Subitems of inherent impls have their own publicity. - hir::ItemKind::Impl(.., None, _, ref impl_item_refs) => { - let ty_vis = - self.check(item.id, ty::Visibility::Invisible).ty().min_visibility; - self.check(item.id, ty_vis).generics().predicates(); - - for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); - let impl_item_vis = ty::Visibility::from_hir(&impl_item.vis, item.id, tcx); - let mut check = self.check(impl_item.id, min(impl_item_vis, ty_vis)); - check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type; - check.generics().predicates().ty(); - - // Recurse for e.g., `impl Trait` (see `visit_ty`). - self.inner_visibility = impl_item_vis; - intravisit::walk_impl_item(self, impl_item); - } - } // A trait impl is public when both its type and its trait are public // Subitems of trait impls have inherited publicity. - hir::ItemKind::Impl(.., Some(_), _, ref impl_item_refs) => { - let vis = self.check(item.id, ty::Visibility::Invisible) - .ty().impl_trait_ref().min_visibility; - self.check(item.id, vis).generics().predicates(); + hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { + let impl_vis = impl_min::(tcx, &Default::default(), item.id); + self.check(item.id, impl_vis).generics().predicates(); for impl_item_ref in impl_item_refs { - let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); - let mut check = self.check(impl_item.id, vis); + let impl_item = tcx.hir().impl_item(impl_item_ref.id); + let impl_item_vis = if trait_ref.is_none() { + min(ty::Visibility::from_hir(&impl_item.vis, item.id, tcx), impl_vis, tcx) + } else { + impl_vis + }; + let mut check = self.check(impl_item.id, impl_item_vis); check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type; check.generics().predicates().ty(); - - // Recurse for e.g., `impl Trait` (see `visit_ty`). - self.inner_visibility = vis; - intravisit::walk_impl_item(self, impl_item); } } } } - - fn visit_impl_item(&mut self, _impl_item: &'tcx hir::ImplItem) { - // Handled in `visit_item` above. - } - - // Don't recurse into expressions in array sizes or const initializers. - fn visit_expr(&mut self, _: &'tcx hir::Expr) {} - // Don't recurse into patterns in function arguments. - fn visit_pat(&mut self, _: &'tcx hir::Pat) {} } pub fn provide(providers: &mut Providers) { @@ -1724,7 +1631,6 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, in_body: false, span: krate.span, empty_tables: &empty_tables, - visited_opaque_tys: FxHashSet::default() }; intravisit::walk_crate(&mut visitor, krate); @@ -1770,7 +1676,6 @@ fn privacy_access_levels<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx, has_pub_restricted, old_error_set: &visitor.old_error_set, - inner_visibility: ty::Visibility::Public, }; krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); } diff --git a/src/libstd/sys/windows/handle.rs b/src/libstd/sys/windows/handle.rs index 7d12e0f6ef085..855efbd3eb5d6 100644 --- a/src/libstd/sys/windows/handle.rs +++ b/src/libstd/sys/windows/handle.rs @@ -160,11 +160,6 @@ impl RawHandle { } } - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - let mut me = self; - (&mut me).read_to_end(buf) - } - pub fn write(&self, buf: &[u8]) -> io::Result { let mut amt = 0; let len = cmp::min(buf.len(), ::max_value() as usize) as c::DWORD; diff --git a/src/libstd/sys/windows/stdio.rs b/src/libstd/sys/windows/stdio.rs index f331397db8cf3..a4f4bd22cd921 100644 --- a/src/libstd/sys/windows/stdio.rs +++ b/src/libstd/sys/windows/stdio.rs @@ -128,11 +128,6 @@ impl Stdin { // MemReader shouldn't error here since we just filled it utf8.read(buf) } - - pub fn read_to_end(&self, buf: &mut Vec) -> io::Result { - let mut me = self; - (&mut me).read_to_end(buf) - } } #[unstable(reason = "not public", issue = "0", feature = "fd_read")] diff --git a/src/test/ui/error-codes/E0445.rs b/src/test/ui/error-codes/E0445.rs index 570c37ef2ccbe..a9a3aee2500fb 100644 --- a/src/test/ui/error-codes/E0445.rs +++ b/src/test/ui/error-codes/E0445.rs @@ -4,12 +4,9 @@ trait Foo { pub trait Bar : Foo {} //~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait pub struct Bar2(pub T); //~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait pub fn foo (t: T) {} //~^ ERROR private trait `Foo` in public interface [E0445] -//~| NOTE can't leak private trait fn main() {} diff --git a/src/test/ui/error-codes/E0445.stderr b/src/test/ui/error-codes/E0445.stderr index 747e4daf74ec2..d0d6ebe16c7f7 100644 --- a/src/test/ui/error-codes/E0445.stderr +++ b/src/test/ui/error-codes/E0445.stderr @@ -5,13 +5,13 @@ LL | pub trait Bar : Foo {} | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `Foo` in public interface - --> $DIR/E0445.rs:8:1 + --> $DIR/E0445.rs:7:1 | LL | pub struct Bar2(pub T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `Foo` in public interface - --> $DIR/E0445.rs:11:1 + --> $DIR/E0445.rs:9:1 | LL | pub fn foo (t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait diff --git a/src/test/ui/impl-trait/issue-49376.rs b/src/test/ui/impl-trait/issue-49376.rs index 4a45988e45d7f..13671b8dbf448 100644 --- a/src/test/ui/impl-trait/issue-49376.rs +++ b/src/test/ui/impl-trait/issue-49376.rs @@ -9,9 +9,11 @@ fn gen() -> impl PartialOrd + PartialEq + Debug { } struct Bar {} trait Foo {} +trait FooNested> {} impl Foo for Bar {} +impl FooNested for Bar {} -fn foo() -> impl Foo { +fn foo() -> impl Foo + FooNested { Bar {} } diff --git a/src/test/ui/issues/issue-18389.stderr b/src/test/ui/issues/issue-18389.stderr index 9cbe8c05b7e3d..02ff6b6d5bff4 100644 --- a/src/test/ui/issues/issue-18389.stderr +++ b/src/test/ui/issues/issue-18389.stderr @@ -1,6 +1,9 @@ error[E0445]: private trait `Private<::P, ::R>` in public interface --> $DIR/issue-18389.rs:7:1 | +LL | trait Private { + | - `Private<::P, ::R>` declared as private +... LL | / pub trait Public: Private< LL | | //~^ ERROR private trait `Private<::P, ::R>` in public interface LL | | ::P, diff --git a/src/test/ui/privacy/private-in-public-expr-pat.rs b/src/test/ui/privacy/private-in-public-expr-pat.rs new file mode 100644 index 0000000000000..a3e53bdf45de3 --- /dev/null +++ b/src/test/ui/privacy/private-in-public-expr-pat.rs @@ -0,0 +1,13 @@ +// Patterns and expressions are not interface parts and don't produce private-in-public errors. + +// compile-pass + +struct Priv1(usize); +struct Priv2; + +pub struct Pub(Priv2); + +pub fn public_expr(_: [u8; Priv1(0).0]) {} // OK +pub fn public_pat(Pub(Priv2): Pub) {} // OK + +fn main() {} diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.rs b/src/test/ui/privacy/private-in-public-non-principal-2.rs new file mode 100644 index 0000000000000..95bf24e7b0f8d --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal-2.rs @@ -0,0 +1,13 @@ +#![feature(optin_builtin_traits)] + +#[allow(private_in_public)] +mod m { + pub trait PubPrincipal {} + auto trait PrivNonPrincipal {} + pub fn leak_dyn_nonprincipal() -> Box { loop {} } +} + +fn main() { + m::leak_dyn_nonprincipal(); + //~^ ERROR type `(dyn m::PubPrincipal + m::PrivNonPrincipal + 'static)` is private +} diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.stderr b/src/test/ui/privacy/private-in-public-non-principal-2.stderr new file mode 100644 index 0000000000000..e15ca9d6dd410 --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal-2.stderr @@ -0,0 +1,8 @@ +error: type `(dyn m::PubPrincipal + m::PrivNonPrincipal + 'static)` is private + --> $DIR/private-in-public-non-principal-2.rs:11:5 + | +LL | m::leak_dyn_nonprincipal(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/privacy/private-in-public-non-principal.rs b/src/test/ui/privacy/private-in-public-non-principal.rs new file mode 100644 index 0000000000000..df2f224c403ac --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal.rs @@ -0,0 +1,20 @@ +#![feature(optin_builtin_traits)] + +pub trait PubPrincipal {} +auto trait PrivNonPrincipal {} + +pub fn leak_dyn_nonprincipal() -> Box { loop {} } +//~^ WARN private type `(dyn PubPrincipal + PrivNonPrincipal + 'static)` in public interface +//~| WARN this was previously accepted + +#[deny(missing_docs)] +fn container() { + impl dyn PubPrincipal { + pub fn check_doc_lint() {} //~ ERROR missing documentation for a method + } + impl dyn PubPrincipal + PrivNonPrincipal { + pub fn check_doc_lint() {} // OK, no missing doc lint + } +} + +fn main() {} diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr new file mode 100644 index 0000000000000..6c9da53ad3fe0 --- /dev/null +++ b/src/test/ui/privacy/private-in-public-non-principal.stderr @@ -0,0 +1,24 @@ +warning: private type `(dyn PubPrincipal + PrivNonPrincipal + 'static)` in public interface (error E0446) + --> $DIR/private-in-public-non-principal.rs:6:1 + | +LL | pub fn leak_dyn_nonprincipal() -> Box { loop {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: #[warn(private_in_public)] on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 + +error: missing documentation for a method + --> $DIR/private-in-public-non-principal.rs:13:9 + | +LL | pub fn check_doc_lint() {} //~ ERROR missing documentation for a method + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/private-in-public-non-principal.rs:10:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/privacy/private-in-public-warn.rs b/src/test/ui/privacy/private-in-public-warn.rs index 0da0d03595d83..29f365b69be4d 100644 --- a/src/test/ui/privacy/private-in-public-warn.rs +++ b/src/test/ui/privacy/private-in-public-warn.rs @@ -213,6 +213,15 @@ mod aliases_pub { impl PrivUseAliasTr for ::AssocAlias { type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface } + impl PrivUseAliasTr for Option<::AssocAlias> { + type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + } + impl PrivUseAliasTr for (::AssocAlias, Priv) { + type Check = Priv; // OK + } + impl PrivUseAliasTr for Option<(::AssocAlias, Priv)> { + type Check = Priv; // OK + } } mod aliases_priv { diff --git a/src/test/ui/privacy/private-in-public-warn.stderr b/src/test/ui/privacy/private-in-public-warn.stderr index ab9ff8d64d36c..8f9e7cd74f992 100644 --- a/src/test/ui/privacy/private-in-public-warn.stderr +++ b/src/test/ui/privacy/private-in-public-warn.stderr @@ -297,8 +297,17 @@ LL | struct Priv; LL | type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface | ^^^^^^^^^^^^^^^^^^ can't leak private type +error[E0446]: private type `aliases_pub::Priv` in public interface + --> $DIR/private-in-public-warn.rs:217:9 + | +LL | struct Priv; + | - `aliases_pub::Priv` declared as private +... +LL | type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface + | ^^^^^^^^^^^^^^^^^^ can't leak private type + error: private trait `aliases_priv::PrivTr1` in public interface (error E0445) - --> $DIR/private-in-public-warn.rs:238:5 + --> $DIR/private-in-public-warn.rs:247:5 | LL | pub trait Tr1: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -306,8 +315,8 @@ LL | pub trait Tr1: PrivUseAliasTr {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 -error: private type `aliases_priv::Priv2` in public interface (error E0446) - --> $DIR/private-in-public-warn.rs:241:5 +error: private trait `aliases_priv::PrivTr1` in public interface (error E0445) + --> $DIR/private-in-public-warn.rs:250:5 | LL | pub trait Tr2: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -315,8 +324,8 @@ LL | pub trait Tr2: PrivUseAliasTr {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 -error: private trait `aliases_priv::PrivTr1` in public interface (error E0445) - --> $DIR/private-in-public-warn.rs:241:5 +error: private type `aliases_priv::Priv2` in public interface (error E0446) + --> $DIR/private-in-public-warn.rs:250:5 | LL | pub trait Tr2: PrivUseAliasTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -324,6 +333,6 @@ LL | pub trait Tr2: PrivUseAliasTr {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 -error: aborting due to 35 previous errors +error: aborting due to 36 previous errors For more information about this error, try `rustc --explain E0446`. diff --git a/src/test/ui/privacy/private-in-public.rs b/src/test/ui/privacy/private-in-public.rs index 288298cfbfcf6..08c00f44f2269 100644 --- a/src/test/ui/privacy/private-in-public.rs +++ b/src/test/ui/privacy/private-in-public.rs @@ -102,7 +102,7 @@ mod aliases_pub { // This should be OK, but associated type aliases are not substituted yet pub fn f3(arg: ::Assoc) {} - //~^ ERROR private type `::Assoc` in public interface + //~^ ERROR private trait `aliases_pub::PrivTr` in public interface //~| ERROR private type `aliases_pub::Priv` in public interface impl PrivUseAlias { @@ -131,7 +131,7 @@ mod aliases_priv { pub fn f1(arg: PrivUseAlias) {} //~ ERROR private type `aliases_priv::Priv1` in public interface pub fn f2(arg: PrivAlias) {} //~ ERROR private type `aliases_priv::Priv2` in public interface pub fn f3(arg: ::Assoc) {} - //~^ ERROR private type `::Assoc` in public + //~^ ERROR private trait `aliases_priv::PrivTr` in public interface //~| ERROR private type `aliases_priv::Priv` in public interface } diff --git a/src/test/ui/privacy/private-in-public.stderr b/src/test/ui/privacy/private-in-public.stderr index 2bd7503ab5aae..bf88a83e633cc 100644 --- a/src/test/ui/privacy/private-in-public.stderr +++ b/src/test/ui/privacy/private-in-public.stderr @@ -82,24 +82,36 @@ LL | pub fn f2() -> Priv { panic!() } //~ ERROR private type `types::Pri error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:31:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub enum E { V(T) } //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:32:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub fn f(arg: T) {} //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:33:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub struct S1(T); //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:34:5 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | / impl Pub { //~ ERROR private trait `traits::PrivTr` in public interface LL | | pub fn f(arg: U) {} //~ ERROR private trait `traits::PrivTr` in public interface LL | | } @@ -108,30 +120,45 @@ LL | | } error[E0445]: private trait `traits::PrivTr` in public interface --> $DIR/private-in-public.rs:35:9 | +LL | trait PrivTr {} + | - `traits::PrivTr` declared as private +... LL | pub fn f(arg: U) {} //~ ERROR private trait `traits::PrivTr` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:44:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub enum E where T: PrivTr { V(T) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:46:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub fn f(arg: T) where T: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:48:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub struct S1(T) where T: PrivTr; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:50:5 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | / impl Pub where T: PrivTr { LL | | //~^ ERROR private trait `traits_where::PrivTr` in public interface LL | | pub fn f(arg: U) where U: PrivTr {} @@ -142,6 +169,9 @@ LL | | } error[E0445]: private trait `traits_where::PrivTr` in public interface --> $DIR/private-in-public.rs:52:9 | +LL | trait PrivTr {} + | - `traits_where::PrivTr` declared as private +... LL | pub fn f(arg: U) where U: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait @@ -181,14 +211,14 @@ LL | struct Priv; LL | pub fn f(arg: Priv) {} //~ ERROR private type `impls::Priv` in public interface | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type -error[E0446]: private type `::Assoc` in public interface +error[E0445]: private trait `aliases_pub::PrivTr` in public interface --> $DIR/private-in-public.rs:104:5 | LL | trait PrivTr { - | - `::Assoc` declared as private + | - `aliases_pub::PrivTr` declared as private ... LL | pub fn f3(arg: ::Assoc) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0446]: private type `aliases_pub::Priv` in public interface --> $DIR/private-in-public.rs:104:5 @@ -226,14 +256,14 @@ LL | struct Priv2; LL | pub fn f2(arg: PrivAlias) {} //~ ERROR private type `aliases_priv::Priv2` in public interface | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type -error[E0446]: private type `::Assoc` in public interface +error[E0445]: private trait `aliases_priv::PrivTr` in public interface --> $DIR/private-in-public.rs:133:5 | LL | trait PrivTr { - | - `::Assoc` declared as private + | - `aliases_priv::PrivTr` declared as private ... LL | pub fn f3(arg: ::Assoc) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0446]: private type `aliases_priv::Priv` in public interface --> $DIR/private-in-public.rs:133:5 From 60d1fa70bbb017632f43c206e5f16b0b5bbd0149 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 31 Dec 2018 03:02:40 +0300 Subject: [PATCH 2/2] Address review comments Say "trait" instead of "type" in diagnostics for `dyn Trait` --- src/librustc/util/ppaux.rs | 3 + src/librustc_privacy/lib.rs | 181 ++++++++++-------- .../associated-item-privacy-type-binding.rs | 12 +- ...ssociated-item-privacy-type-binding.stderr | 12 +- .../private-in-public-non-principal-2.rs | 2 +- .../private-in-public-non-principal-2.stderr | 2 +- .../private-in-public-non-principal.rs | 2 +- .../private-in-public-non-principal.stderr | 2 +- src/test/ui/privacy/private-inferred-type.rs | 2 +- .../ui/privacy/private-inferred-type.stderr | 4 +- 10 files changed, 126 insertions(+), 96 deletions(-) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d5e6bb9a2e2a5..318d7adb19011 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -709,6 +709,9 @@ define_print! { define_print! { ('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) { + display { + cx.parameterized(f, self.substs, self.def_id, &[]) + } debug { ty::tls::with(|tcx| { let dummy_self = tcx.mk_infer(ty::FreshTy(0)); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 0cd8c9da57e29..c6626c1551f4a 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -23,6 +23,7 @@ use rustc::middle::privacy::{AccessLevel, AccessLevels}; use rustc::ty::{self, TyCtxt, Ty, TraitRef, TypeFoldable, GenericParamDefKind}; use rustc::ty::fold::TypeVisitor; use rustc::ty::query::Providers; +use rustc::ty::subst::Substs; use rustc::util::nodemap::NodeSet; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; @@ -31,8 +32,7 @@ use syntax::attr; use syntax::symbol::keywords; use syntax_pos::Span; -use std::{cmp, fmt}; -use std::mem::replace; +use std::{cmp, fmt, mem}; use std::marker::PhantomData; mod diagnostics; @@ -43,6 +43,12 @@ mod diagnostics; /// Implemented to visit all `DefId`s in a type. /// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them. +/// The idea is to visit "all components of a type", as documented in +/// https://github.com/rust-lang/rfcs/blob/master/text/2145-type-privacy.md#how-to-determine-visibility-of-a-type +/// 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 def-ids +/// manually. Second, it doesn't visit some type components like signatures of fn types, or traits +/// in `impl Trait`, see individual commits in `DefIdVisitorSkeleton::visit_ty`. trait DefIdVisitor<'a, 'tcx: 'a> { fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>; fn recurse_into_assoc_tys(&self) -> bool { true } @@ -79,33 +85,38 @@ impl<'a, 'tcx, V> DefIdVisitorSkeleton<'_, 'a, 'tcx, V> where V: DefIdVisitor<'a, 'tcx> + ?Sized { fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> bool { - self.def_id_visitor.visit_def_id(trait_ref.def_id, "trait", &trait_ref) || - trait_ref.visit_with(self) + let TraitRef { def_id, substs } = trait_ref; + self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) || substs.visit_with(self) } fn visit_predicates(&mut self, predicates: Lrc>) -> bool { - for (predicate, _) in &predicates.predicates { - let trait_ref = match predicate { + let ty::GenericPredicates { parent: _, predicates } = &*predicates; + for (predicate, _span) in predicates { + match predicate { ty::Predicate::Trait(poly_predicate) => { - poly_predicate.skip_binder().trait_ref + let ty::TraitPredicate { trait_ref } = *poly_predicate.skip_binder(); + if self.visit_trait(trait_ref) { + return true; + } } ty::Predicate::Projection(poly_predicate) => { - if poly_predicate.skip_binder().ty.visit_with(self) { + let ty::ProjectionPredicate { projection_ty, ty } = + *poly_predicate.skip_binder(); + if ty.visit_with(self) { + return true; + } + if self.visit_trait(projection_ty.trait_ref(self.def_id_visitor.tcx())) { return true; } - poly_predicate.skip_binder().projection_ty.trait_ref(self.def_id_visitor.tcx()) } ty::Predicate::TypeOutlives(poly_predicate) => { - if poly_predicate.skip_binder().0.visit_with(self) { + let ty::OutlivesPredicate(ty, _region) = *poly_predicate.skip_binder(); + if ty.visit_with(self) { return true; } - continue; } - ty::Predicate::RegionOutlives(..) => continue, + ty::Predicate::RegionOutlives(..) => {}, _ => bug!("unexpected predicate: {:?}", predicate), - }; - if self.visit_trait(trait_ref) { - return true; } } false @@ -117,6 +128,7 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { let tcx = self.def_id_visitor.tcx(); + // Substs are not visited here because they are visited below in `super_visit_with`. match ty.sty { ty::Adt(&ty::AdtDef { did: def_id, .. }, ..) | ty::Foreign(def_id) | @@ -126,14 +138,18 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> if self.def_id_visitor.visit_def_id(def_id, "type", ty) { return true; } - // Default type visitor doesn't visit fn signatures. + // 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. if let ty::FnDef(..) = ty.sty { if tcx.fn_sig(def_id).visit_with(self) { return true; } } - // Inherent static methods don't have self type in substs, - // we have to check it additionally. + // Inherent static methods don't have self type in substs. + // Something like `fn() {my_method}` type of the method + // `impl Pub { pub fn my_method() {} }` is considered a private type, + // so we need to visit the self type additionally. if let Some(assoc_item) = tcx.opt_associated_item(def_id) { if let ty::ImplContainer(impl_def_id) = assoc_item.container { if tcx.type_of(impl_def_id).visit_with(self) { @@ -156,12 +172,14 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> } ty::Dynamic(predicates, ..) => { for predicate in *predicates.skip_binder() { - let def_id = match *predicate { - ty::ExistentialPredicate::Trait(trait_ref) => trait_ref.def_id, - ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx).def_id, - ty::ExistentialPredicate::AutoTrait(def_id) => def_id, + let trait_ref = match *predicate { + ty::ExistentialPredicate::Trait(trait_ref) => trait_ref, + ty::ExistentialPredicate::Projection(proj) => proj.trait_ref(tcx), + ty::ExistentialPredicate::AutoTrait(def_id) => + ty::ExistentialTraitRef { def_id, substs: Substs::empty() }, }; - if self.def_id_visitor.visit_def_id(def_id, "type", ty) { + let ty::ExistentialTraitRef { def_id, substs: _ } = trait_ref; + if self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref) { return true; } } @@ -169,6 +187,9 @@ impl<'a, 'tcx, V> TypeVisitor<'tcx> for DefIdVisitorSkeleton<'_, 'a, 'tcx, V> ty::Opaque(def_id, ..) => { // Skip repeated `Opaque`s to avoid infinite recursion. if self.visited_opaque_tys.insert(def_id) { + // Default type visitor doesn't visit traits in `impl Trait`. + // Something like `impl PrivTr` is considered a private type, + // so we need to visit the traits additionally. if self.visit_predicates(tcx.predicates_of(def_id)) { return true; } @@ -249,24 +270,22 @@ fn def_id_visibility<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) }; (ty::Visibility::from_hir(vis, node_id, tcx), vis.span, vis.node.descr()) } - None => (tcx.visibility(def_id), tcx.def_span(def_id), "private"), + None => { + let vis = tcx.visibility(def_id); + let descr = if vis == ty::Visibility::Public { "public" } else { "private" }; + (vis, tcx.def_span(def_id), descr) + } } } // Set the correct `TypeckTables` for the given `item_id` (or an empty table if // there is no `TypeckTables` for the item). -fn update_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - item_id: ast::NodeId, - tables: &mut &'a ty::TypeckTables<'tcx>, - empty_tables: &'a ty::TypeckTables<'tcx>) - -> &'a ty::TypeckTables<'tcx> { - let def_id = tcx.hir().local_def_id(item_id); - - if tcx.has_typeck_tables(def_id) { - replace(tables, tcx.typeck_tables_of(def_id)) - } else { - replace(tables, empty_tables) - } +fn item_tables<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + node_id: ast::NodeId, + empty_tables: &'a ty::TypeckTables<'tcx>) + -> &'a ty::TypeckTables<'tcx> { + let def_id = tcx.hir().local_def_id(node_id); + if tcx.has_typeck_tables(def_id) { tcx.typeck_tables_of(def_id) } else { empty_tables } } fn min<'a, 'tcx>(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'a, 'tcx, 'tcx>) @@ -298,23 +317,45 @@ impl<'a, 'tcx> Visitor<'tcx> for PubRestrictedVisitor<'a, 'tcx> { /// Visitor used to determine impl visibility and reachability. //////////////////////////////////////////////////////////////////////////////// -struct FindMin<'a, 'tcx, M: Min> { +struct FindMin<'a, 'tcx, VL: VisibilityLike> { tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &'a AccessLevels, - min: M, + min: VL, +} + +impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'a, 'tcx> for FindMin<'a, 'tcx, VL> { + fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } + fn recurse_into_assoc_tys(&self) -> bool { false } + fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { + self.min = VL::new_min(self, def_id); + false + } } -trait Min: Sized { +trait VisibilityLike: Sized { const MAX: Self; fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self; + + // Returns an over-approximation (`recurse_into_assoc_tys` = false) of visibility due to + // associated types for which we can't determine visibility precisely. + fn of_impl<'a, 'tcx>(node_id: ast::NodeId, tcx: TyCtxt<'a, 'tcx, 'tcx>, + access_levels: &'a AccessLevels) -> Self { + let mut find = FindMin { tcx, access_levels, min: Self::MAX }; + let def_id = tcx.hir().local_def_id(node_id); + find.visit(tcx.type_of(def_id)); + if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { + find.visit_trait(trait_ref); + } + find.min + } } -impl Min for ty::Visibility { +impl VisibilityLike for ty::Visibility { const MAX: Self = ty::Visibility::Public; fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { min(def_id_visibility(find.tcx, def_id).0, find.min, find.tcx) } } -impl Min for Option { +impl VisibilityLike for Option { const MAX: Self = Some(AccessLevel::Public); fn new_min<'a, 'tcx>(find: &FindMin<'a, 'tcx, Self>, def_id: DefId) -> Self { cmp::min(if let Some(node_id) = find.tcx.hir().as_local_node_id(def_id) { @@ -325,26 +366,6 @@ impl Min for Option { } } -impl<'a, 'tcx, M: Min> DefIdVisitor<'a, 'tcx> for FindMin<'a, 'tcx, M> { - fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx } - fn recurse_into_assoc_tys(&self) -> bool { false } - fn visit_def_id(&mut self, def_id: DefId, _kind: &str, _descr: &dyn fmt::Display) -> bool { - self.min = M::new_min(self, def_id); - false - } -} - -fn impl_min<'a, 'tcx, M: Min>(tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &'a AccessLevels, - node_id: ast::NodeId) -> M { - let mut find = FindMin { tcx, access_levels, min: M::MAX }; - let def_id = tcx.hir().local_def_id(node_id); - find.visit(tcx.type_of(def_id)); - if let Some(trait_ref) = tcx.impl_trait_ref(def_id) { - find.visit_trait(trait_ref); - } - find.min -} - //////////////////////////////////////////////////////////////////////////////// /// The embargo visitor, used to determine the exports of the ast //////////////////////////////////////////////////////////////////////////////// @@ -404,7 +425,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx hir::Item) { let inherited_item_level = match item.node { hir::ItemKind::Impl(..) => - impl_min::>(self.tcx, &self.access_levels, item.id), + Option::::of_impl(item.id, self.tcx, &self.access_levels), // Foreign modules inherit level from parents. hir::ItemKind::ForeignMod(..) => self.prev_level, // Other `pub` items inherit levels from parents. @@ -575,7 +596,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { } } - let orig_level = replace(&mut self.prev_level, item_level); + let orig_level = mem::replace(&mut self.prev_level, item_level); intravisit::walk_item(self, item); self.prev_level = orig_level; } @@ -584,7 +605,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> { // Blocks can have public items, for example impls, but they always // start as completely private regardless of publicity of a function, // constant, type, field, etc., in which this block resides. - let orig_level = replace(&mut self.prev_level, None); + let orig_level = mem::replace(&mut self.prev_level, None); intravisit::walk_block(self, b); self.prev_level = orig_level; } @@ -732,28 +753,31 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body)); + let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = orig_tables; } fn visit_item(&mut self, item: &'tcx hir::Item) { - let orig_current_item = replace(&mut self.current_item, item.id); - let orig_tables = update_tables(self.tcx, item.id, &mut self.tables, self.empty_tables); + let orig_current_item = mem::replace(&mut self.current_item, item.id); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables)); intravisit::walk_item(self, item); self.current_item = orig_current_item; self.tables = orig_tables; } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables)); intravisit::walk_trait_item(self, ti); self.tables = orig_tables; } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables)); intravisit::walk_impl_item(self, ii); self.tables = orig_tables; } @@ -864,8 +888,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } fn visit_nested_body(&mut self, body: hir::BodyId) { - let orig_tables = replace(&mut self.tables, self.tcx.body_tables(body)); - let orig_in_body = replace(&mut self.in_body, true); + let orig_tables = mem::replace(&mut self.tables, self.tcx.body_tables(body)); + let orig_in_body = mem::replace(&mut self.in_body, true); let body = self.tcx.hir().body(body); self.visit_body(body); self.tables = orig_tables; @@ -1003,9 +1027,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { // Check types in item interfaces. fn visit_item(&mut self, item: &'tcx hir::Item) { let orig_current_item = - replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id)); - let orig_in_body = replace(&mut self.in_body, false); - let orig_tables = update_tables(self.tcx, item.id, &mut self.tables, self.empty_tables); + mem::replace(&mut self.current_item, self.tcx.hir().local_def_id(item.id)); + let orig_in_body = mem::replace(&mut self.in_body, false); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, item.id, self.empty_tables)); intravisit::walk_item(self, item); self.tables = orig_tables; self.in_body = orig_in_body; @@ -1013,13 +1038,15 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { } fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { - let orig_tables = update_tables(self.tcx, ti.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ti.id, self.empty_tables)); intravisit::walk_trait_item(self, ti); self.tables = orig_tables; } fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { - let orig_tables = update_tables(self.tcx, ii.id, &mut self.tables, self.empty_tables); + let orig_tables = + mem::replace(&mut self.tables, item_tables(self.tcx, ii.id, self.empty_tables)); intravisit::walk_impl_item(self, ii); self.tables = orig_tables; } @@ -1576,7 +1603,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> // A trait impl is public when both its type and its trait are public // Subitems of trait impls have inherited publicity. hir::ItemKind::Impl(.., ref trait_ref, _, ref impl_item_refs) => { - let impl_vis = impl_min::(tcx, &Default::default(), item.id); + let impl_vis = ty::Visibility::of_impl(item.id, tcx, &Default::default()); self.check(item.id, impl_vis).generics().predicates(); for impl_item_ref in impl_item_refs { let impl_item = tcx.hir().impl_item(impl_item_ref.id); diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.rs b/src/test/ui/privacy/associated-item-privacy-type-binding.rs index ff274ab8f1f8d..591e9df81eb0b 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.rs +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.rs @@ -9,19 +9,19 @@ mod priv_trait { pub macro mac1() { let _: Box>; - //~^ ERROR type `(dyn priv_trait::PubTr + ')` is private - //~| ERROR type `(dyn priv_trait::PubTr + ')` is private + //~^ ERROR trait `priv_trait::PrivTr` is private + //~| ERROR trait `priv_trait::PrivTr` is private type InSignatureTy2 = Box>; - //~^ ERROR type `(dyn priv_trait::PubTr + 'static)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private trait InSignatureTr2: PubTr {} //~^ ERROR trait `priv_trait::PrivTr` is private } pub macro mac2() { let _: Box>; - //~^ ERROR type `(dyn priv_trait::PrivTr + ')` is private - //~| ERROR type `(dyn priv_trait::PrivTr + ')` is private + //~^ ERROR trait `priv_trait::PrivTr` is private + //~| ERROR trait `priv_trait::PrivTr` is private type InSignatureTy1 = Box>; - //~^ ERROR type `(dyn priv_trait::PrivTr + 'static)` is private + //~^ ERROR trait `priv_trait::PrivTr` is private trait InSignatureTr1: PrivTr {} //~^ ERROR trait `priv_trait::PrivTr` is private } diff --git a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr index 331e2f689b547..7f6886d7f9ad4 100644 --- a/src/test/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/src/test/ui/privacy/associated-item-privacy-type-binding.stderr @@ -1,4 +1,4 @@ -error: type `(dyn priv_trait::PubTr + ')` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:13 | LL | let _: Box>; @@ -7,7 +7,7 @@ LL | let _: Box>; LL | priv_trait::mac1!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PubTr + ')` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:16 | LL | let _: Box>; @@ -16,7 +16,7 @@ LL | let _: Box>; LL | priv_trait::mac1!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PubTr + 'static)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:14:31 | LL | type InSignatureTy2 = Box>; @@ -34,7 +34,7 @@ LL | trait InSignatureTr2: PubTr {} LL | priv_trait::mac1!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PrivTr + ')` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:13 | LL | let _: Box>; @@ -43,7 +43,7 @@ LL | let _: Box>; LL | priv_trait::mac2!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PrivTr + ')` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:16 | LL | let _: Box>; @@ -52,7 +52,7 @@ LL | let _: Box>; LL | priv_trait::mac2!(); | -------------------- in this macro invocation -error: type `(dyn priv_trait::PrivTr + 'static)` is private +error: trait `priv_trait::PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:23:31 | LL | type InSignatureTy1 = Box>; diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.rs b/src/test/ui/privacy/private-in-public-non-principal-2.rs index 95bf24e7b0f8d..02fd92aa7a4ef 100644 --- a/src/test/ui/privacy/private-in-public-non-principal-2.rs +++ b/src/test/ui/privacy/private-in-public-non-principal-2.rs @@ -9,5 +9,5 @@ mod m { fn main() { m::leak_dyn_nonprincipal(); - //~^ ERROR type `(dyn m::PubPrincipal + m::PrivNonPrincipal + 'static)` is private + //~^ ERROR trait `m::PrivNonPrincipal` is private } diff --git a/src/test/ui/privacy/private-in-public-non-principal-2.stderr b/src/test/ui/privacy/private-in-public-non-principal-2.stderr index e15ca9d6dd410..2db4925722642 100644 --- a/src/test/ui/privacy/private-in-public-non-principal-2.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal-2.stderr @@ -1,4 +1,4 @@ -error: type `(dyn m::PubPrincipal + m::PrivNonPrincipal + 'static)` is private +error: trait `m::PrivNonPrincipal` is private --> $DIR/private-in-public-non-principal-2.rs:11:5 | LL | m::leak_dyn_nonprincipal(); diff --git a/src/test/ui/privacy/private-in-public-non-principal.rs b/src/test/ui/privacy/private-in-public-non-principal.rs index df2f224c403ac..5de5a685208cd 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.rs +++ b/src/test/ui/privacy/private-in-public-non-principal.rs @@ -4,7 +4,7 @@ pub trait PubPrincipal {} auto trait PrivNonPrincipal {} pub fn leak_dyn_nonprincipal() -> Box { loop {} } -//~^ WARN private type `(dyn PubPrincipal + PrivNonPrincipal + 'static)` in public interface +//~^ WARN private trait `PrivNonPrincipal` in public interface //~| WARN this was previously accepted #[deny(missing_docs)] diff --git a/src/test/ui/privacy/private-in-public-non-principal.stderr b/src/test/ui/privacy/private-in-public-non-principal.stderr index 6c9da53ad3fe0..9967405589777 100644 --- a/src/test/ui/privacy/private-in-public-non-principal.stderr +++ b/src/test/ui/privacy/private-in-public-non-principal.stderr @@ -1,4 +1,4 @@ -warning: private type `(dyn PubPrincipal + PrivNonPrincipal + 'static)` in public interface (error E0446) +warning: private trait `PrivNonPrincipal` in public interface (error E0445) --> $DIR/private-in-public-non-principal.rs:6:1 | LL | pub fn leak_dyn_nonprincipal() -> Box { loop {} } diff --git a/src/test/ui/privacy/private-inferred-type.rs b/src/test/ui/privacy/private-inferred-type.rs index 1eb5fa408cd7f..69b60a56c67f1 100644 --- a/src/test/ui/privacy/private-inferred-type.rs +++ b/src/test/ui/privacy/private-inferred-type.rs @@ -119,7 +119,7 @@ fn main() { m::leak_anon2(); //~ ERROR type `m::Priv` is private m::leak_anon3(); //~ ERROR type `m::Priv` is private - m::leak_dyn1(); //~ ERROR type `(dyn m::Trait + 'static)` is private + m::leak_dyn1(); //~ ERROR trait `m::Trait` is private m::leak_dyn2(); //~ ERROR type `m::Priv` is private m::leak_dyn3(); //~ ERROR type `m::Priv` is private diff --git a/src/test/ui/privacy/private-inferred-type.stderr b/src/test/ui/privacy/private-inferred-type.stderr index 089fb1d3c3ea8..80a475f7dceea 100644 --- a/src/test/ui/privacy/private-inferred-type.stderr +++ b/src/test/ui/privacy/private-inferred-type.stderr @@ -160,10 +160,10 @@ error: type `m::Priv` is private LL | m::leak_anon3(); //~ ERROR type `m::Priv` is private | ^^^^^^^^^^^^^^^ -error: type `(dyn m::Trait + 'static)` is private +error: trait `m::Trait` is private --> $DIR/private-inferred-type.rs:122:5 | -LL | m::leak_dyn1(); //~ ERROR type `(dyn m::Trait + 'static)` is private +LL | m::leak_dyn1(); //~ ERROR trait `m::Trait` is private | ^^^^^^^^^^^^^^ error: type `m::Priv` is private