Auto merge of #29973 - petrochenkov:privinpub, r=nikomatsakis

Some notes:
This patch enforces the rules from [RFC 136](https://github.com/rust-lang/rfcs/blob/master/text/0136-no-privates-in-public.md) and makes "private in public" a module-level concept and not crate-level. Only `pub` annotations are used by the new algorithm, crate-level exported node set produced by `EmbargoVisitor` is not used. The error messages are tweaked accordingly and don't use the word "exported" to avoid confusing people (https://github.com/rust-lang/rust/issues/29668).

The old algorithm tried to be extra smart with impls, but it mostly led to unpredictable behavior and bugs like https://github.com/rust-lang/rust/issues/28325.
The new algorithm tries to be as simple as possible - an impl is considered public iff its type is public and its trait is public (if presents).
A type or trait is considered public if all its components are public, [complications](https://internals.rust-lang.org/t/limits-of-type-inference-smartness/2919) with private types leaking to other crates/modules through trait impls and type inference are deliberately ignored so far.

The new algorithm is not recursive and uses the nice new facility `Crate::visit_all_items`!

Obsolete pre-1.0 feature `visible_private_types` is removed.

This is a [breaking-change].
The two main vectors of breakage are type aliases (https://github.com/rust-lang/rust/issues/28450) and impls (https://github.com/rust-lang/rust/issues/28325).
I need some statistics from a crater run (cc @alexcrichton) to decide on the breakage mitigation strategy.
UPDATE: All the new errors are reported as warnings controlled by a lint `private_in_public` and lint group `future_incompatible`, but the intent is to make them hard errors eventually.

Closes https://github.com/rust-lang/rust/issues/28325
Closes https://github.com/rust-lang/rust/issues/28450
Closes https://github.com/rust-lang/rust/issues/29524
Closes https://github.com/rust-lang/rust/issues/29627
Closes https://github.com/rust-lang/rust/issues/29668
Closes https://github.com/rust-lang/rust/issues/30055

r? @nikomatsakis
This commit is contained in:
bors 2015-12-18 18:54:52 +00:00
commit ef91cdb140
30 changed files with 808 additions and 320 deletions

View File

@ -2372,10 +2372,6 @@ The currently implemented features of the reference compiler are:
Such items should not be allowed by the compiler to exist,
so if you need this there probably is a compiler bug.
* `visible_private_types` - Allows public APIs to expose otherwise private
types, e.g. as the return type of a public function.
This capability may be removed in the future.
* `allow_internal_unstable` - Allows `macro_rules!` macros to be tagged with the
`#[allow_internal_unstable]` attribute, designed
to allow `std` macros to call

View File

@ -78,7 +78,7 @@ pub struct Node<K, V> {
_capacity: usize,
}
struct NodeSlice<'a, K: 'a, V: 'a> {
pub struct NodeSlice<'a, K: 'a, V: 'a> {
keys: &'a [K],
vals: &'a [V],
pub edges: &'a [Node<K, V>],
@ -87,7 +87,7 @@ struct NodeSlice<'a, K: 'a, V: 'a> {
has_edges: bool,
}
struct MutNodeSlice<'a, K: 'a, V: 'a> {
pub struct MutNodeSlice<'a, K: 'a, V: 'a> {
keys: &'a [K],
vals: &'a mut [V],
pub edges: &'a mut [Node<K, V>],
@ -1344,7 +1344,7 @@ fn min_load_from_capacity(cap: usize) -> usize {
/// A trait for pairs of `Iterator`s, one over edges and the other over key/value pairs. This is
/// necessary, as the `MoveTraversalImpl` needs to have a destructor that deallocates the `Node`,
/// and a pair of `Iterator`s would require two independent destructors.
trait TraversalImpl {
pub trait TraversalImpl {
type Item;
type Edge;
@ -1358,7 +1358,7 @@ trait TraversalImpl {
/// A `TraversalImpl` that actually is backed by two iterators. This works in the non-moving case,
/// as no deallocation needs to be done.
#[derive(Clone)]
struct ElemsAndEdges<Elems, Edges>(Elems, Edges);
pub struct ElemsAndEdges<Elems, Edges>(Elems, Edges);
impl<K, V, E, Elems: DoubleEndedIterator, Edges: DoubleEndedIterator>
TraversalImpl for ElemsAndEdges<Elems, Edges>
@ -1375,7 +1375,7 @@ impl<K, V, E, Elems: DoubleEndedIterator, Edges: DoubleEndedIterator>
}
/// A `TraversalImpl` taking a `Node` by value.
struct MoveTraversalImpl<K, V> {
pub struct MoveTraversalImpl<K, V> {
keys: RawItems<K>,
vals: RawItems<V>,
edges: RawItems<Node<K, V>>,
@ -1436,7 +1436,7 @@ impl<K, V> Drop for MoveTraversalImpl<K, V> {
/// An abstraction over all the different kinds of traversals a node supports
#[derive(Clone)]
struct AbsTraversal<Impl> {
pub struct AbsTraversal<Impl> {
inner: Impl,
head_is_edge: bool,
tail_is_edge: bool,

View File

@ -117,6 +117,13 @@ declare_lint! {
Allow,
"detects trivial casts of numeric types which could be removed"
}
declare_lint! {
pub PRIVATE_IN_PUBLIC,
Warn,
"detect private items in public interfaces not caught by the old implementation"
}
/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
@ -141,6 +148,7 @@ impl LintPass for HardwiredLints {
FAT_PTR_TRANSMUTES,
TRIVIAL_CASTS,
TRIVIAL_NUMERIC_CASTS,
PRIVATE_IN_PUBLIC,
CONST_ERR
)
}

View File

@ -146,6 +146,9 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES);
add_lint_group!(sess, "future_incompatible",
PRIVATE_IN_PUBLIC);
// We have one lint pass defined specially
store.register_late_pass(sess, false, box lint::GatherNodeLevels);

View File

@ -209,7 +209,7 @@ struct ArmBlocks {
}
#[derive(Clone, Debug)]
struct Candidate<'pat, 'tcx:'pat> {
pub struct Candidate<'pat, 'tcx:'pat> {
// all of these must be satisfied...
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
@ -235,7 +235,7 @@ struct Binding<'tcx> {
}
#[derive(Clone, Debug)]
struct MatchPair<'pat, 'tcx:'pat> {
pub struct MatchPair<'pat, 'tcx:'pat> {
// this lvalue...
lvalue: Lvalue<'tcx>,
@ -278,7 +278,7 @@ enum TestKind<'tcx> {
}
#[derive(Debug)]
struct Test<'tcx> {
pub struct Test<'tcx> {
span: Span,
kind: TestKind<'tcx>,
}

View File

@ -18,7 +18,7 @@ use rustc_front::hir;
use syntax::ast;
use syntax::codemap::Span;
struct Builder<'a, 'tcx: 'a> {
pub struct Builder<'a, 'tcx: 'a> {
hir: Cx<'a, 'tcx>,
cfg: CFG<'tcx>,
scopes: Vec<scope::Scope<'tcx>>,
@ -40,7 +40,7 @@ struct CFG<'tcx> {
// convenient.
#[must_use] // if you don't use one of these results, you're leaving a dangling edge
struct BlockAnd<T>(BasicBlock, T);
pub struct BlockAnd<T>(BasicBlock, T);
trait BlockAndExtension {
fn and<T>(self, v: T) -> BlockAnd<T>;

View File

@ -21,13 +21,14 @@ trait Foo {
fn dummy(&self) { }
}
pub trait Bar : Foo {} // error: private trait in exported type parameter bound
pub trait Bar : Foo {} // error: private trait in public interface
pub struct Bar<T: Foo>(pub T); // same error
pub fn foo<T: Foo> (t: T) {} // same error
```
To solve this error, please ensure that the trait is also public and accessible
at the same level of the public functions or types which are bound on it.
To solve this error, please ensure that the trait is also public. The trait
can be made inaccessible if necessary by placing it into a private inner module,
but it still has to be marked with `pub`.
Example:
```
@ -42,20 +43,22 @@ pub fn foo<T: Foo> (t: T) {} // ok!
"##,
E0446: r##"
A private type was used in an exported type signature. Erroneous code example:
A private type was used in a public type signature. Erroneous code example:
```
mod Foo {
struct Bar(u32);
pub fn bar() -> Bar { // error: private type in exported type signature
pub fn bar() -> Bar { // error: private type in public interface
Bar(0)
}
}
```
To solve this error, please ensure that the type is also public and accessible
at the same level of the public functions or types which use it. Example:
To solve this error, please ensure that the type is also public. The type
can be made inaccessible if necessary by placing it into a private inner module,
but it still has to be marked with `pub`.
Example:
```
mod Foo {

View File

@ -38,6 +38,7 @@ use std::mem::replace;
use rustc_front::hir;
use rustc_front::intravisit::{self, Visitor};
use rustc::lint;
use rustc::middle::def;
use rustc::middle::def_id::DefId;
use rustc::middle::privacy::{AccessLevel, AccessLevels};
@ -46,7 +47,7 @@ use rustc::middle::privacy::LastPrivate::*;
use rustc::middle::privacy::PrivateDep::*;
use rustc::middle::privacy::ExternalExports;
use rustc::middle::ty;
use rustc::util::nodemap::NodeMap;
use rustc::util::nodemap::{NodeMap, NodeSet};
use rustc::front::map as ast_map;
use syntax::ast;
@ -1101,14 +1102,23 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
}
}
struct VisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
///////////////////////////////////////////////////////////////////////////////
/// Obsolete visitors for checking for private items in public interfaces.
/// These visitors are supposed to be kept in frozen state and produce an
/// "old error node set". For backward compatibility the new visitor reports
/// warnings instead of hard errors when the erroneous node is not in this old set.
///////////////////////////////////////////////////////////////////////////////
struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>,
access_levels: &'a AccessLevels,
in_variant: bool,
// set of errors produced by this obsolete visitor
old_error_set: NodeSet,
}
struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
inner: &'a VisiblePrivateTypesVisitor<'b, 'tcx>,
struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
inner: &'a ObsoleteVisiblePrivateTypesVisitor<'b, 'tcx>,
/// whether the type refers to private types.
contains_private: bool,
/// whether we've recurred at all (i.e. if we're pointing at the
@ -1118,7 +1128,7 @@ struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
outer_type_is_public_path: bool,
}
impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
// `int` etc. (None doesn't seem to occur.)
@ -1146,14 +1156,11 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
self.access_levels.is_public(trait_id)
}
fn check_ty_param_bound(&self,
fn check_ty_param_bound(&mut self,
ty_param_bound: &hir::TyParamBound) {
if let hir::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
if !self.tcx.sess.features.borrow().visible_private_types &&
self.path_is_private_type(trait_ref.trait_ref.ref_id) {
let span = trait_ref.trait_ref.path.span;
span_err!(self.tcx.sess, span, E0445,
"private trait in exported type parameter bound");
if self.path_is_private_type(trait_ref.trait_ref.ref_id) {
self.old_error_set.insert(trait_ref.trait_ref.ref_id);
}
}
}
@ -1163,7 +1170,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
}
}
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
fn visit_ty(&mut self, ty: &hir::Ty) {
if let hir::TyPath(..) = ty.node {
if self.inner.path_is_private_type(ty.id) {
@ -1183,7 +1190,7 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 't
fn visit_expr(&mut self, _: &hir::Expr) {}
}
impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'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.
fn visit_nested_item(&mut self, item: hir::ItemId) {
@ -1224,7 +1231,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
// check the properties of the Self type:
{
let mut visitor = CheckTypeForPrivatenessVisitor {
let mut visitor = ObsoleteCheckTypeForPrivatenessVisitor {
inner: self,
contains_private: false,
at_outer_type: true,
@ -1401,11 +1408,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
fn visit_ty(&mut self, t: &hir::Ty) {
debug!("VisiblePrivateTypesVisitor checking ty {:?}", t);
if let hir::TyPath(_, ref p) = t.node {
if !self.tcx.sess.features.borrow().visible_private_types &&
self.path_is_private_type(t.id) {
span_err!(self.tcx.sess, p.span, E0446,
"private type in exported type signature");
if let hir::TyPath(..) = t.node {
if self.path_is_private_type(t.id) {
self.old_error_set.insert(t.id);
}
}
intravisit::walk_ty(self, t)
@ -1439,6 +1444,235 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
fn visit_expr(&mut self, _: &hir::Expr) {}
}
///////////////////////////////////////////////////////////////////////////////
/// SearchInterfaceForPrivateItemsVisitor traverses an item's interface and
/// finds any private components in it.
/// PrivateItemsInPublicInterfacesVisitor ensures there are no private types
/// and traits in public interfaces.
///////////////////////////////////////////////////////////////////////////////
struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>,
// Do not report an error when a private type is found
is_quiet: bool,
// Is private component found?
is_public: bool,
old_error_set: &'a NodeSet,
}
impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
// Check if the type alias contain private types when substituted
fn is_public_type_alias(&self, item: &hir::Item, path: &hir::Path) -> bool {
// We substitute type aliases only when determining impl publicity
// FIXME: This will probably change and all type aliases will be substituted,
// requires an amendment to RFC 136.
if !self.is_quiet {
return false
}
// Type alias is considered public if the aliased type is
// public, even if the type alias itself is private. So, something
// like `type A = u8; pub fn f() -> A {...}` doesn't cause an error.
if let hir::ItemTy(ref ty, ref generics) = item.node {
let mut check = SearchInterfaceForPrivateItemsVisitor { is_public: true, ..*self };
check.visit_ty(ty);
// If a private type alias with default type parameters is used in public
// interface we must ensure, that the defaults are public if they are actually used.
// ```
// type Alias<T = Private> = T;
// pub fn f() -> Alias {...} // `Private` is implicitly used here, so it must be public
// ```
let provided_params = path.segments.last().unwrap().parameters.types().len();
for ty_param in &generics.ty_params[provided_params..] {
if let Some(ref default_ty) = ty_param.default {
check.visit_ty(default_ty);
}
}
check.is_public
} else {
false
}
}
}
impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
fn visit_ty(&mut self, ty: &hir::Ty) {
if self.is_quiet && !self.is_public {
// We are in quiet mode and a private type is already found, no need to proceed
return
}
if let hir::TyPath(_, ref path) = ty.node {
let def = self.tcx.def_map.borrow().get(&ty.id).unwrap().full_def();
match def {
def::DefPrimTy(..) | def::DefSelfTy(..) | def::DefTyParam(..) => {
// Public
}
def::DefAssociatedTy(..) if self.is_quiet => {
// Conservatively approximate the whole type alias as public without
// recursing into its components when determining impl publicity.
// For example, `impl <Type as Trait>::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
}
def::DefStruct(def_id) | def::DefTy(def_id, _) |
def::DefTrait(def_id) | def::DefAssociatedTy(def_id, _) => {
// Non-local means public (private items can't leave their crate, modulo bugs)
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
let item = self.tcx.map.expect_item(node_id);
if item.vis != hir::Public && !self.is_public_type_alias(item, path) {
if !self.is_quiet {
if self.old_error_set.contains(&ty.id) {
span_err!(self.tcx.sess, ty.span, E0446,
"private type in public interface");
} else {
self.tcx.sess.add_lint (
lint::builtin::PRIVATE_IN_PUBLIC,
node_id,
ty.span,
"private type in public interface (error E0446)".to_string()
);
}
}
self.is_public = false;
}
}
}
_ => {}
}
}
intravisit::walk_ty(self, ty);
}
fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) {
if self.is_quiet && !self.is_public {
// We are in quiet mode and a private type is already found, no need to proceed
return
}
// Non-local means public (private items can't leave their crate, modulo bugs)
let def_id = self.tcx.trait_ref_to_def_id(trait_ref);
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
let item = self.tcx.map.expect_item(node_id);
if item.vis != hir::Public {
if !self.is_quiet {
if self.old_error_set.contains(&trait_ref.ref_id) {
span_err!(self.tcx.sess, trait_ref.path.span, E0445,
"private trait in public interface");
} else {
self.tcx.sess.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
node_id,
trait_ref.path.span,
"private trait in public interface (error E0445)"
.to_string());
}
}
self.is_public = false;
}
}
intravisit::walk_trait_ref(self, trait_ref);
}
// Don't recurse into function bodies
fn visit_block(&mut self, _: &hir::Block) {}
// Don't recurse into expressions in array sizes or const initializers
fn visit_expr(&mut self, _: &hir::Expr) {}
// Don't recurse into patterns in function arguments
fn visit_pat(&mut self, _: &hir::Pat) {}
}
struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>,
old_error_set: &'a NodeSet,
}
impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
// A type is considered public if it doesn't contain any private components
fn is_public_ty(&self, ty: &hir::Ty) -> bool {
let mut check = SearchInterfaceForPrivateItemsVisitor {
tcx: self.tcx, is_quiet: true, is_public: true, old_error_set: self.old_error_set
};
check.visit_ty(ty);
check.is_public
}
// A trait reference is considered public if it doesn't contain any private components
fn is_public_trait_ref(&self, trait_ref: &hir::TraitRef) -> bool {
let mut check = SearchInterfaceForPrivateItemsVisitor {
tcx: self.tcx, is_quiet: true, is_public: true, old_error_set: self.old_error_set
};
check.visit_trait_ref(trait_ref);
check.is_public
}
}
impl<'a, 'tcx, 'v> Visitor<'v> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
let mut check = SearchInterfaceForPrivateItemsVisitor {
tcx: self.tcx, is_quiet: false, is_public: true, old_error_set: self.old_error_set
};
match item.node {
// Crates are always public
hir::ItemExternCrate(..) => {}
// All nested items are checked by visit_item
hir::ItemMod(..) => {}
// Checked in resolve
hir::ItemUse(..) => {}
// Subitems of these items have inherited publicity
hir::ItemConst(..) | hir::ItemStatic(..) | hir::ItemFn(..) |
hir::ItemEnum(..) | hir::ItemTrait(..) | hir::ItemTy(..) => {
if item.vis == hir::Public {
check.visit_item(item);
}
}
// Subitems of foreign modules have their own publicity
hir::ItemForeignMod(ref foreign_mod) => {
for foreign_item in &foreign_mod.items {
if foreign_item.vis == hir::Public {
check.visit_foreign_item(foreign_item);
}
}
}
// Subitems of structs have their own publicity
hir::ItemStruct(ref struct_def, ref generics) => {
if item.vis == hir::Public {
check.visit_generics(generics);
for field in struct_def.fields() {
if field.node.kind.visibility() == hir::Public {
check.visit_struct_field(field);
}
}
}
}
// The interface is empty
hir::ItemDefaultImpl(..) => {}
// An inherent impl is public when its type is public
// Subitems of inherent impls have their own publicity
hir::ItemImpl(_, _, ref generics, None, ref ty, ref impl_items) => {
if self.is_public_ty(ty) {
check.visit_generics(generics);
for impl_item in impl_items {
if impl_item.vis == hir::Public {
check.visit_impl_item(impl_item);
}
}
}
}
// A trait impl is public when both its type and its trait are public
// Subitems of trait impls have inherited publicity
hir::ItemImpl(_, _, ref generics, Some(ref trait_ref), ref ty, ref impl_items) => {
if self.is_public_ty(ty) && self.is_public_trait_ref(trait_ref) {
check.visit_generics(generics);
for impl_item in impl_items {
check.visit_impl_item(impl_item);
}
}
}
}
}
}
pub fn check_crate(tcx: &ty::ctxt,
export_map: &def::ExportMap,
external_exports: ExternalExports)
@ -1492,18 +1726,24 @@ pub fn check_crate(tcx: &ty::ctxt,
}
visitor.update(ast::CRATE_NODE_ID, Some(AccessLevel::Public));
let EmbargoVisitor { access_levels, .. } = visitor;
{
let mut visitor = VisiblePrivateTypesVisitor {
let mut visitor = ObsoleteVisiblePrivateTypesVisitor {
tcx: tcx,
access_levels: &access_levels,
access_levels: &visitor.access_levels,
in_variant: false,
old_error_set: NodeSet(),
};
intravisit::walk_crate(&mut visitor, krate);
// Check for private types and traits in public interfaces
let mut visitor = PrivateItemsInPublicInterfacesVisitor {
tcx: tcx,
old_error_set: &visitor.old_error_set,
};
krate.visit_all_items(&mut visitor);
}
access_levels
visitor.access_levels
}
__build_diagnostic_array! { librustc_privacy, DIAGNOSTICS }

View File

@ -390,9 +390,15 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
let module = Module::new(parent_link, Some(def), false, is_public);
name_bindings.define_module(module.clone(), sp);
let variant_modifiers = if is_public {
DefModifiers::empty()
} else {
DefModifiers::PRIVATE_VARIANT
};
for variant in &(*enum_definition).variants {
let item_def_id = self.ast_map.local_def_id(item.id);
self.build_reduced_graph_for_variant(variant, item_def_id, &module);
self.build_reduced_graph_for_variant(variant, item_def_id,
&module, variant_modifiers);
}
parent.clone()
}
@ -494,7 +500,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
fn build_reduced_graph_for_variant(&mut self,
variant: &Variant,
item_id: DefId,
parent: &Rc<Module>) {
parent: &Rc<Module>,
variant_modifiers: DefModifiers) {
let name = variant.node.name;
let is_exported = if variant.node.data.is_struct() {
// Not adding fields for variants as they are not accessed with a self receiver
@ -512,12 +519,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
self.ast_map.local_def_id(variant.node.data.id()),
is_exported),
variant.span,
DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers);
child.define_type(DefVariant(item_id,
self.ast_map.local_def_id(variant.node.data.id()),
is_exported),
variant.span,
DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
DefModifiers::PUBLIC | DefModifiers::IMPORTABLE | variant_modifiers);
}
/// Constructs the reduced graph for one foreign item.

View File

@ -905,8 +905,13 @@ impl fmt::Debug for Module {
bitflags! {
#[derive(Debug)]
flags DefModifiers: u8 {
// Enum variants are always considered `PUBLIC`, this is needed for `use Enum::Variant`
// or `use Enum::*` to work on private enums.
const PUBLIC = 1 << 0,
const IMPORTABLE = 1 << 1,
// Variants are considered `PUBLIC`, but some of them live in private enums.
// We need to track them to prohibit reexports like `pub use PrivEnum::Variant`.
const PRIVATE_VARIANT = 1 << 2,
}
}

View File

@ -25,6 +25,7 @@ use {resolve_error, ResolutionError};
use build_reduced_graph;
use rustc::lint;
use rustc::middle::def::*;
use rustc::middle::def_id::DefId;
use rustc::middle::privacy::*;
@ -452,6 +453,17 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
self.resolver.session.span_note(directive.span, &note_msg);
pub_err = true;
}
if directive.is_public && child_name_bindings.value_ns.
defined_with(DefModifiers::PRIVATE_VARIANT) {
let msg = format!("variant `{}` is private, and cannot be reexported ( \
error E0364), consider declaring its enum as `pub`",
source);
self.resolver.session.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
directive.id,
directive.span,
msg);
pub_err = true;
}
}
if child_name_bindings.type_ns.defined() {
debug!("(resolving single import) found type binding");
@ -465,6 +477,16 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
span_err!(self.resolver.session, directive.span, E0365, "{}", &msg);
self.resolver.session.span_note(directive.span, &note_msg);
}
if !pub_err && directive.is_public && child_name_bindings.type_ns.
defined_with(DefModifiers::PRIVATE_VARIANT) {
let msg = format!("variant `{}` is private, and cannot be reexported ( \
error E0365), consider declaring its enum as `pub`",
source);
self.resolver.session.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
directive.id,
directive.span,
msg);
}
}
}
}
@ -842,10 +864,22 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
module_to_string(module_));
// Merge the child item into the import resolution.
// pub_err makes sure we don't give the same error twice.
let mut pub_err = false;
{
let mut merge_child_item = |namespace| {
let modifier = DefModifiers::IMPORTABLE | DefModifiers::PUBLIC;
if !pub_err && is_public &&
name_bindings[namespace].defined_with(DefModifiers::PRIVATE_VARIANT) {
let msg = format!("variant `{}` is private, and cannot be reexported (error \
E0364), consider declaring its enum as `pub`", name);
self.resolver.session.add_lint(lint::builtin::PRIVATE_IN_PUBLIC,
import_directive.id,
import_directive.span,
msg);
pub_err = true;
}
let modifier = DefModifiers::IMPORTABLE | DefModifiers::PUBLIC;
if name_bindings[namespace].defined_with(modifier) {
let namespace_name = match namespace {
TypeNS => "type",

View File

@ -14,7 +14,7 @@ use std::os::windows::prelude::*;
use std::ptr;
use libc::{c_void, c_long};
type DWORD = u32;
pub type DWORD = u32;
type LPCWSTR = *const u16;
type LONG = c_long;
type LPDWORD = *mut DWORD;
@ -34,7 +34,7 @@ const SYNCHRONIZE: REGSAM = 0x00100000;
const REG_SZ: DWORD = 1;
const ERROR_SUCCESS: i32 = 0;
enum __HKEY__ {}
pub enum __HKEY__ {}
pub type HKEY = *mut __HKEY__;
pub type PHKEY = *mut HKEY;
pub type REGSAM = DWORD;

View File

@ -145,7 +145,7 @@ impl FunctionDebugContext {
}
}
struct FunctionDebugContextData {
pub struct FunctionDebugContextData {
scope_map: RefCell<NodeMap<DIScope>>,
fn_metadata: DISubprogram,
argument_counter: Cell<usize>,

View File

@ -123,7 +123,7 @@ pub enum BucketState<K, V, M> {
// A GapThenFull encapsulates the state of two consecutive buckets at once.
// The first bucket, called the gap, is known to be empty.
// The second bucket is full.
struct GapThenFull<K, V, M> {
pub struct GapThenFull<K, V, M> {
gap: EmptyBucket<K, V, ()>,
full: FullBucket<K, V, M>,
}

View File

@ -82,7 +82,7 @@ const KNOWN_FEATURES: &'static [(&'static str, &'static str, Option<u32>, Status
("advanced_slice_patterns", "1.0.0", Some(23121), Active),
("tuple_indexing", "1.0.0", None, Accepted),
("associated_types", "1.0.0", None, Accepted),
("visible_private_types", "1.0.0", Some(29627), Active),
("visible_private_types", "1.0.0", None, Removed),
("slicing_syntax", "1.0.0", None, Accepted),
("box_syntax", "1.0.0", Some(27779), Active),
("placement_in_syntax", "1.0.0", Some(27779), Active),
@ -514,7 +514,6 @@ pub enum AttributeGate {
pub struct Features {
pub unboxed_closures: bool,
pub rustc_diagnostic_macros: bool,
pub visible_private_types: bool,
pub allow_quote: bool,
pub allow_asm: bool,
pub allow_log_syntax: bool,
@ -551,7 +550,6 @@ impl Features {
Features {
unboxed_closures: false,
rustc_diagnostic_macros: false,
visible_private_types: false,
allow_quote: false,
allow_asm: false,
allow_log_syntax: false,
@ -1130,7 +1128,6 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
Features {
unboxed_closures: cx.has_feature("unboxed_closures"),
rustc_diagnostic_macros: cx.has_feature("rustc_diagnostic_macros"),
visible_private_types: cx.has_feature("visible_private_types"),
allow_quote: cx.has_feature("quote"),
allow_asm: cx.has_feature("asm"),
allow_log_syntax: cx.has_feature("log_syntax"),

View File

@ -13,7 +13,7 @@
use std::marker;
struct arc_destruct<T: Sync> {
pub struct arc_destruct<T: Sync> {
_data: isize,
_marker: marker::PhantomData<T>
}
@ -37,7 +37,7 @@ fn init() -> arc_destruct<context_res> {
arc(context_res())
}
struct context_res {
pub struct context_res {
ctx : isize,
}

View File

@ -14,7 +14,7 @@ use foo::NoResult; // Through a re-export
mod foo {
pub use self::MyEnum::NoResult;
enum MyEnum {
pub enum MyEnum {
Result,
NoResult
}

View File

@ -14,7 +14,7 @@ use std::any::TypeId;
trait Private<P, R> {
fn call(&self, p: P, r: R);
}
pub trait Public: Private< //~ ERROR private trait in exported type parameter bound
pub trait Public: Private< //~ ERROR private trait in public interface
<Self as Public>::P,
<Self as Public>::R
> {

View File

@ -49,7 +49,7 @@ struct UsedStruct1 {
}
struct UsedStruct2(isize);
struct UsedStruct3;
struct UsedStruct4;
pub struct UsedStruct4;
// this struct is never used directly, but its method is, so we don't want
// to warn it
struct SemiUsedStruct;

View File

@ -1,123 +0,0 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![allow(dead_code)]
#![crate_type="lib"]
use std::marker;
struct Private<T>(marker::PhantomData<T>);
pub struct Public<T>(marker::PhantomData<T>);
impl Private<Public<isize>> {
pub fn a(&self) -> Private<isize> { panic!() }
fn b(&self) -> Private<isize> { panic!() }
pub fn c() -> Private<isize> { panic!() }
fn d() -> Private<isize> { panic!() }
}
impl Private<isize> {
pub fn e(&self) -> Private<isize> { panic!() }
fn f(&self) -> Private<isize> { panic!() }
}
impl Public<Private<isize>> {
pub fn a(&self) -> Private<isize> { panic!() }
fn b(&self) -> Private<isize> { panic!() }
pub fn c() -> Private<isize> { panic!() } //~ ERROR private type in exported type signature
fn d() -> Private<isize> { panic!() }
}
impl Public<isize> {
pub fn e(&self) -> Private<isize> { panic!() } //~ ERROR private type in exported type signature
fn f(&self) -> Private<isize> { panic!() }
}
pub fn x(_: Private<isize>) {} //~ ERROR private type in exported type signature
fn y(_: Private<isize>) {}
pub struct Foo {
pub x: Private<isize>, //~ ERROR private type in exported type signature
y: Private<isize>
}
struct Bar {
x: Private<isize>,
}
pub enum Baz {
Baz1(Private<isize>), //~ ERROR private type in exported type signature
Baz2 {
y: Private<isize> //~ ERROR private type in exported type signature
},
}
enum Qux {
Qux1(Private<isize>),
Qux2 {
x: Private<isize>,
}
}
pub trait PubTrait {
fn foo(&self) -> Private<isize> { panic!( )} //~ ERROR private type in exported type signature
fn bar(&self) -> Private<isize>; //~ ERROR private type in exported type signature
fn baz() -> Private<isize>; //~ ERROR private type in exported type signature
}
impl PubTrait for Public<isize> {
fn bar(&self) -> Private<isize> { panic!() }
fn baz() -> Private<isize> { panic!() }
}
impl PubTrait for Public<Private<isize>> {
fn bar(&self) -> Private<isize> { panic!() }
fn baz() -> Private<isize> { panic!() }
}
impl PubTrait for Private<isize> {
fn bar(&self) -> Private<isize> { panic!() }
fn baz() -> Private<isize> { panic!() }
}
impl PubTrait for (Private<isize>,) {
fn bar(&self) -> Private<isize> { panic!() }
fn baz() -> Private<isize> { panic!() }
}
trait PrivTrait {
fn foo(&self) -> Private<isize> { panic!( )}
fn bar(&self) -> Private<isize>;
}
impl PrivTrait for Private<isize> {
fn bar(&self) -> Private<isize> { panic!() }
}
impl PrivTrait for (Private<isize>,) {
fn bar(&self) -> Private<isize> { panic!() }
}
pub trait ParamTrait<T> {
fn foo() -> T;
}
impl ParamTrait<Private<isize>> //~ ERROR private type in exported type signature
for Public<isize> {
fn foo() -> Private<isize> { panic!() }
}
impl ParamTrait<Private<isize>> for Private<isize> {
fn foo() -> Private<isize> { panic!( )}
}
impl<T: ParamTrait<Private<isize>>> //~ ERROR private type in exported type signature
ParamTrait<T> for Public<i8> {
fn foo() -> T { panic!() }
}

View File

@ -1,28 +0,0 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that we properly check for private types in public signatures, even
// inside a private module (#22261).
mod a {
struct Priv;
pub fn expose_a() -> Priv { //~Error: private type in exported type signature
panic!();
}
mod b {
pub fn expose_b() -> super::Priv { //~Error: private type in exported type signature
panic!();
}
}
}
pub fn main() {}

View File

@ -8,16 +8,26 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// pretty-expanded FIXME #23616
mod m1 {
#![deny(private_in_public)]
#![feature(visible_private_types)]
pub struct Pub;
struct Priv;
trait Foo { fn dummy(&self) { } }
impl Pub {
pub fn f() -> Priv {} //~ ERROR private type in public interface
}
}
pub trait Bar : Foo {}
mod m2 {
#![deny(future_incompatible)]
struct Baz;
pub struct Pub;
struct Priv;
pub fn f(_: Baz) {}
impl Pub {
pub fn f() -> Priv {} //~ ERROR private type in public interface
}
}
fn main() {}

View File

@ -0,0 +1,251 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Private types and traits are not allowed in public interfaces.
// This test also ensures that the checks are performed even inside private modules.
#![feature(rustc_attrs)]
#![feature(associated_consts)]
#![feature(associated_type_defaults)]
#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(improper_ctypes)]
mod types {
struct Priv;
pub struct Pub;
pub trait PubTr {
type Alias;
}
pub type Alias = Priv; //~ WARN private type in public interface
pub enum E {
V1(Priv), //~ WARN private type in public interface
V2 { field: Priv }, //~ WARN private type in public interface
}
pub trait Tr {
const C: Priv = Priv; //~ WARN private type in public interface
type Alias = Priv; //~ WARN private type in public interface
fn f1(arg: Priv) {} //~ WARN private type in public interface
fn f2() -> Priv { panic!() } //~ WARN private type in public interface
}
extern {
pub static ES: Priv; //~ WARN private type in public interface
pub fn ef1(arg: Priv); //~ WARN private type in public interface
pub fn ef2() -> Priv; //~ WARN private type in public interface
}
impl PubTr for Pub {
type Alias = Priv; //~ WARN private type in public interface
}
}
mod traits {
trait PrivTr {}
pub struct Pub<T>(T);
pub trait PubTr {}
pub type Alias<T: PrivTr> = T; //~ WARN private trait in public interface
//~^ WARN trait bounds are not (yet) enforced in type definitions
pub trait Tr1: PrivTr {} //~ WARN private trait in public interface
pub trait Tr2<T: PrivTr> {} //~ WARN private trait in public interface
pub trait Tr3 {
type Alias: PrivTr; //~ WARN private trait in public interface
fn f<T: PrivTr>(arg: T) {} //~ WARN private trait in public interface
}
impl<T: PrivTr> Pub<T> {} //~ WARN private trait in public interface
impl<T: PrivTr> PubTr for Pub<T> {} //~ WARN private trait in public interface
}
mod traits_where {
trait PrivTr {}
pub struct Pub<T>(T);
pub trait PubTr {}
pub type Alias<T> where T: PrivTr = T; //~ WARN private trait in public interface
pub trait Tr2<T> where T: PrivTr {} //~ WARN private trait in public interface
pub trait Tr3 {
fn f<T>(arg: T) where T: PrivTr {} //~ WARN private trait in public interface
}
impl<T> Pub<T> where T: PrivTr {} //~ WARN private trait in public interface
impl<T> PubTr for Pub<T> where T: PrivTr {} //~ WARN private trait in public interface
}
mod generics {
struct Priv<T = u8>(T);
pub struct Pub<T = u8>(T);
trait PrivTr<T> {}
pub trait PubTr<T> {}
pub trait Tr1: PrivTr<Pub> {} //~ WARN private trait in public interface
pub trait Tr2: PubTr<Priv> {} //~ WARN private type in public interface
pub trait Tr3: PubTr<[Priv; 1]> {} //~ WARN private type in public interface
pub trait Tr4: PubTr<Pub<Priv>> {} //~ WARN private type in public interface
}
mod impls {
struct Priv;
pub struct Pub;
trait PrivTr {
type Alias;
}
pub trait PubTr {
type Alias;
}
impl Priv {
pub fn f(arg: Priv) {} // OK
}
impl PrivTr for Priv {
type Alias = Priv; // OK
}
impl PubTr for Priv {
type Alias = Priv; // OK
}
impl PrivTr for Pub {
type Alias = Priv; // OK
}
impl PubTr for Pub {
type Alias = Priv; //~ WARN private type in public interface
}
}
mod impls_generics {
struct Priv<T = u8>(T);
pub struct Pub<T = u8>(T);
trait PrivTr<T = u8> {
type Alias;
}
pub trait PubTr<T = u8> {
type Alias;
}
impl Priv<Pub> {
pub fn f(arg: Priv) {} // OK
}
impl Pub<Priv> {
pub fn f(arg: Priv) {} // OK
}
impl PrivTr<Pub> for Priv {
type Alias = Priv; // OK
}
impl PubTr<Priv> for Priv {
type Alias = Priv; // OK
}
impl PubTr for Priv<Pub> {
type Alias = Priv; // OK
}
impl PubTr for [Priv; 1] {
type Alias = Priv; // OK
}
impl PubTr for Pub<Priv> {
type Alias = Priv; // OK
}
impl PrivTr<Pub> for Pub {
type Alias = Priv; // OK
}
impl PubTr<Priv> for Pub {
type Alias = Priv; // OK
}
}
mod aliases_pub {
struct Priv;
mod m {
pub struct Pub1;
pub struct Pub2;
pub struct Pub3;
pub trait PubTr<T = u8> {
type Check = u8;
}
}
use self::m::Pub1 as PrivUseAlias;
use self::m::PubTr as PrivUseAliasTr;
type PrivAlias = m::Pub2;
trait PrivTr {
type AssocAlias = m::Pub3;
}
impl PrivTr for Priv {}
pub fn f1(arg: PrivUseAlias) {} // OK
pub trait Tr1: PrivUseAliasTr {} // OK
// This should be OK, if type aliases are substituted
pub trait Tr2: PrivUseAliasTr<PrivAlias> {} //~ WARN private type in public interface
impl PrivAlias {
pub fn f(arg: Priv) {} //~ WARN private type in public interface
}
// This doesn't even parse
// impl <Priv as PrivTr>::AssocAlias {
// pub fn f(arg: Priv) {} // WARN private type in public interface
// }
impl PrivUseAliasTr for PrivUseAlias {
type Check = Priv; //~ WARN private type in public interface
}
impl PrivUseAliasTr for PrivAlias {
type Check = Priv; //~ WARN private type in public interface
}
impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
type Check = Priv; //~ WARN private type in public interface
}
}
mod aliases_priv {
struct Priv;
struct Priv1;
struct Priv2;
struct Priv3;
trait PrivTr1<T = u8> {
type Check = u8;
}
use self::Priv1 as PrivUseAlias;
use self::PrivTr1 as PrivUseAliasTr;
type PrivAlias = Priv2;
trait PrivTr {
type AssocAlias = Priv3;
}
impl PrivTr for Priv {}
pub trait Tr1: PrivUseAliasTr {} //~ WARN private trait in public interface
pub trait Tr2: PrivUseAliasTr<PrivAlias> {} //~ WARN private trait in public interface
//~^ WARN private type in public interface
impl PrivUseAlias {
pub fn f(arg: Priv) {} // OK
}
impl PrivAlias {
pub fn f(arg: Priv) {} // OK
}
// This doesn't even parse
// impl <Priv as PrivTr>::AssocAlias {
// pub fn f(arg: Priv) {} // OK
// }
impl PrivUseAliasTr for PrivUseAlias {
type Check = Priv; // OK
}
impl PrivUseAliasTr for PrivAlias {
type Check = Priv; // OK
}
impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
type Check = Priv; // OK
}
}
mod aliases_params {
struct Priv;
type PrivAliasGeneric<T = Priv> = T;
type Result<T> = ::std::result::Result<T, Priv>;
}
#[rustc_error]
fn main() {} //~ ERROR compilation successful

View File

@ -0,0 +1,152 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Private types and traits are not allowed in public interfaces.
// This test also ensures that the checks are performed even inside private modules.
#![feature(associated_consts)]
#![feature(associated_type_defaults)]
mod types {
struct Priv;
pub struct Pub;
pub trait PubTr {
type Alias;
}
pub const C: Priv = Priv; //~ ERROR private type in public interface
pub static S: Priv = Priv; //~ ERROR private type in public interface
pub fn f1(arg: Priv) {} //~ ERROR private type in public interface
pub fn f2() -> Priv { panic!() } //~ ERROR private type in public interface
pub struct S1(pub Priv); //~ ERROR private type in public interface
pub struct S2 { pub field: Priv } //~ ERROR private type in public interface
impl Pub {
pub const C: Priv = Priv; //~ ERROR private type in public interface
pub fn f1(arg: Priv) {} //~ ERROR private type in public interface
pub fn f2() -> Priv { panic!() } //~ ERROR private type in public interface
}
}
mod traits {
trait PrivTr {}
pub struct Pub<T>(T);
pub trait PubTr {}
pub enum E<T: PrivTr> { V(T) } //~ ERROR private trait in public interface
pub fn f<T: PrivTr>(arg: T) {} //~ ERROR private trait in public interface
pub struct S1<T: PrivTr>(T); //~ ERROR private trait in public interface
impl<T: PrivTr> Pub<T> {
pub fn f<U: PrivTr>(arg: U) {} //~ ERROR private trait in public interface
}
}
mod traits_where {
trait PrivTr {}
pub struct Pub<T>(T);
pub trait PubTr {}
pub enum E<T> where T: PrivTr { V(T) } //~ ERROR private trait in public interface
pub fn f<T>(arg: T) where T: PrivTr {} //~ ERROR private trait in public interface
pub struct S1<T>(T) where T: PrivTr; //~ ERROR private trait in public interface
impl<T> Pub<T> where T: PrivTr {
pub fn f<U>(arg: U) where U: PrivTr {} //~ ERROR private trait in public interface
}
}
mod generics {
struct Priv<T = u8>(T);
pub struct Pub<T = u8>(T);
trait PrivTr<T> {}
pub trait PubTr<T> {}
pub fn f1(arg: [Priv; 1]) {} //~ ERROR private type in public interface
pub fn f2(arg: Pub<Priv>) {} //~ ERROR private type in public interface
pub fn f3(arg: Priv<Pub>) {} //~ ERROR private type in public interface
}
mod impls {
struct Priv;
pub struct Pub;
trait PrivTr {
type Alias;
}
pub trait PubTr {
type Alias;
}
impl Pub {
pub fn f(arg: Priv) {} //~ ERROR private type in public interface
}
}
mod aliases_pub {
struct Priv;
mod m {
pub struct Pub1;
pub struct Pub2;
pub struct Pub3;
pub trait PubTr<T = u8> {
type Check = u8;
}
}
use self::m::Pub1 as PrivUseAlias;
use self::m::PubTr as PrivUseAliasTr;
type PrivAlias = m::Pub2;
trait PrivTr {
type AssocAlias = m::Pub3;
}
impl PrivTr for Priv {}
// This should be OK, if type aliases are substituted
pub fn f2(arg: PrivAlias) {} //~ ERROR private type in public interface
// This should be OK, but associated type aliases are not substituted yet
pub fn f3(arg: <Priv as PrivTr>::AssocAlias) {} //~ ERROR private type in public interface
impl PrivUseAlias {
pub fn f(arg: Priv) {} //~ ERROR private type in public interface
}
}
mod aliases_priv {
struct Priv;
struct Priv1;
struct Priv2;
struct Priv3;
trait PrivTr1<T = u8> {
type Check = u8;
}
use self::Priv1 as PrivUseAlias;
use self::PrivTr1 as PrivUseAliasTr;
type PrivAlias = Priv2;
trait PrivTr {
type AssocAlias = Priv3;
}
impl PrivTr for Priv {}
pub fn f1(arg: PrivUseAlias) {} //~ ERROR private type in public interface
pub fn f2(arg: PrivAlias) {} //~ ERROR private type in public interface
pub fn f3(arg: <Priv as PrivTr>::AssocAlias) {} //~ ERROR private type in public interface
}
mod aliases_params {
struct Priv;
type PrivAliasGeneric<T = Priv> = T;
type Result<T> = ::std::result::Result<T, Priv>;
// This should be OK, if type aliases are substituted
pub fn f1(arg: PrivAliasGeneric<u8>) {} //~ ERROR private type in public interface
pub fn f2(arg: PrivAliasGeneric) {} //~ ERROR private type in public interface
pub fn f3(arg: Result<u8>) {} //~ ERROR private type in public interface
}
fn main() {}

View File

@ -8,34 +8,26 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub struct PublicType;
struct PrivateType;
#![feature(rustc_attrs)]
#![allow(dead_code)]
pub trait PublicTrait {
type Item;
mod m1 {
pub use ::E::V; //~ WARN variant `V` is private, and cannot be reexported
}
trait PrivateTrait {
type Item;
mod m2 {
pub use ::E::{V}; //~ WARN variant `V` is private, and cannot be reexported
}
impl PublicTrait for PublicType {
type Item = PrivateType; //~ ERROR private type in exported type signature
mod m3 {
pub use ::E::V::{self}; //~ WARN variant `V` is private, and cannot be reexported
}
// OK
impl PublicTrait for PrivateType {
type Item = PrivateType;
mod m4 {
pub use ::E::*; //~ WARN variant `V` is private, and cannot be reexported
}
// OK
impl PrivateTrait for PublicType {
type Item = PrivateType;
}
enum E { V }
// OK
impl PrivateTrait for PrivateType {
type Item = PrivateType;
}
fn main() {}
#[rustc_error]
fn main() {} //~ ERROR compilation successful

View File

@ -1,67 +0,0 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Foo {
fn dummy(&self) { }
}
pub fn f<
T
: Foo //~ ERROR private trait in exported type parameter bound
>() {}
pub fn g<T>() where
T
: Foo //~ ERROR private trait in exported type parameter bound
{}
pub struct S;
impl S {
pub fn f<
T
: Foo //~ ERROR private trait in exported type parameter bound
>() {}
pub fn g<T>() where
T
: Foo //~ ERROR private trait in exported type parameter bound
{}
}
pub struct S1<
T
: Foo //~ ERROR private trait in exported type parameter bound
> {
x: T
}
pub struct S2<T> where
T
: Foo //~ ERROR private trait in exported type parameter bound
{
x: T
}
pub enum E1<
T
: Foo //~ ERROR private trait in exported type parameter bound
> {
V1(T)
}
pub enum E2<T> where
T
: Foo //~ ERROR private trait in exported type parameter bound
{
V2(T)
}
fn main() {}

View File

@ -182,7 +182,7 @@ use self::Enum1::{Variant1, Variant2};
use std::marker::PhantomData;
use std::ptr;
struct Struct1;
pub struct Struct1;
struct GenericStruct<T1, T2>(PhantomData<(T1,T2)>);
enum Enum1 {

View File

@ -13,11 +13,11 @@
use std::marker::PhantomData;
struct DeterministicHasher;
struct RandomHasher;
pub struct DeterministicHasher;
pub struct RandomHasher;
struct MyHashMap<K, V, H=DeterministicHasher> {
pub struct MyHashMap<K, V, H=DeterministicHasher> {
data: PhantomData<(K, V, H)>
}

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Test { type T; }
pub trait Test { type T; }
impl Test for u32 {
type T = i32;

View File

@ -1,4 +1,4 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,10 +8,18 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
trait Foo {
fn dummy(&self) { }
// Functions can return unnameable types
mod m1 {
mod m2 {
#[derive(Debug)]
pub struct A;
}
use self::m2::A;
pub fn x() -> A { A }
}
pub trait Bar : Foo {} //~ ERROR private trait in exported type
fn main() {}
fn main() {
let x = m1::x();
println!("{:?}", x);
}