Skip to content

Commit ef91cdb

Browse files
committed
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 (#29668). The old algorithm tried to be extra smart with impls, but it mostly led to unpredictable behavior and bugs like #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 (#28450) and impls (#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 #28325 Closes #28450 Closes #29524 Closes #29627 Closes #29668 Closes #30055 r? @nikomatsakis
2 parents 29ea4ee + 785cbe0 commit ef91cdb

30 files changed

+808
-320
lines changed

src/doc/reference.md

-4
Original file line numberDiff line numberDiff line change
@@ -2372,10 +2372,6 @@ The currently implemented features of the reference compiler are:
23722372
Such items should not be allowed by the compiler to exist,
23732373
so if you need this there probably is a compiler bug.
23742374

2375-
* `visible_private_types` - Allows public APIs to expose otherwise private
2376-
types, e.g. as the return type of a public function.
2377-
This capability may be removed in the future.
2378-
23792375
* `allow_internal_unstable` - Allows `macro_rules!` macros to be tagged with the
23802376
`#[allow_internal_unstable]` attribute, designed
23812377
to allow `std` macros to call

src/libcollections/btree/node.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub struct Node<K, V> {
7878
_capacity: usize,
7979
}
8080

81-
struct NodeSlice<'a, K: 'a, V: 'a> {
81+
pub struct NodeSlice<'a, K: 'a, V: 'a> {
8282
keys: &'a [K],
8383
vals: &'a [V],
8484
pub edges: &'a [Node<K, V>],
@@ -87,7 +87,7 @@ struct NodeSlice<'a, K: 'a, V: 'a> {
8787
has_edges: bool,
8888
}
8989

90-
struct MutNodeSlice<'a, K: 'a, V: 'a> {
90+
pub struct MutNodeSlice<'a, K: 'a, V: 'a> {
9191
keys: &'a [K],
9292
vals: &'a mut [V],
9393
pub edges: &'a mut [Node<K, V>],
@@ -1344,7 +1344,7 @@ fn min_load_from_capacity(cap: usize) -> usize {
13441344
/// A trait for pairs of `Iterator`s, one over edges and the other over key/value pairs. This is
13451345
/// necessary, as the `MoveTraversalImpl` needs to have a destructor that deallocates the `Node`,
13461346
/// and a pair of `Iterator`s would require two independent destructors.
1347-
trait TraversalImpl {
1347+
pub trait TraversalImpl {
13481348
type Item;
13491349
type Edge;
13501350

@@ -1358,7 +1358,7 @@ trait TraversalImpl {
13581358
/// A `TraversalImpl` that actually is backed by two iterators. This works in the non-moving case,
13591359
/// as no deallocation needs to be done.
13601360
#[derive(Clone)]
1361-
struct ElemsAndEdges<Elems, Edges>(Elems, Edges);
1361+
pub struct ElemsAndEdges<Elems, Edges>(Elems, Edges);
13621362

13631363
impl<K, V, E, Elems: DoubleEndedIterator, Edges: DoubleEndedIterator>
13641364
TraversalImpl for ElemsAndEdges<Elems, Edges>
@@ -1375,7 +1375,7 @@ impl<K, V, E, Elems: DoubleEndedIterator, Edges: DoubleEndedIterator>
13751375
}
13761376

13771377
/// A `TraversalImpl` taking a `Node` by value.
1378-
struct MoveTraversalImpl<K, V> {
1378+
pub struct MoveTraversalImpl<K, V> {
13791379
keys: RawItems<K>,
13801380
vals: RawItems<V>,
13811381
edges: RawItems<Node<K, V>>,
@@ -1436,7 +1436,7 @@ impl<K, V> Drop for MoveTraversalImpl<K, V> {
14361436

14371437
/// An abstraction over all the different kinds of traversals a node supports
14381438
#[derive(Clone)]
1439-
struct AbsTraversal<Impl> {
1439+
pub struct AbsTraversal<Impl> {
14401440
inner: Impl,
14411441
head_is_edge: bool,
14421442
tail_is_edge: bool,

src/librustc/lint/builtin.rs

+8
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,13 @@ declare_lint! {
117117
Allow,
118118
"detects trivial casts of numeric types which could be removed"
119119
}
120+
121+
declare_lint! {
122+
pub PRIVATE_IN_PUBLIC,
123+
Warn,
124+
"detect private items in public interfaces not caught by the old implementation"
125+
}
126+
120127
/// Does nothing as a lint pass, but registers some `Lint`s
121128
/// which are used by other parts of the compiler.
122129
#[derive(Copy, Clone)]
@@ -141,6 +148,7 @@ impl LintPass for HardwiredLints {
141148
FAT_PTR_TRANSMUTES,
142149
TRIVIAL_CASTS,
143150
TRIVIAL_NUMERIC_CASTS,
151+
PRIVATE_IN_PUBLIC,
144152
CONST_ERR
145153
)
146154
}

src/librustc_lint/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
146146
UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
147147
UNUSED_UNSAFE, PATH_STATEMENTS, UNUSED_ATTRIBUTES);
148148

149+
add_lint_group!(sess, "future_incompatible",
150+
PRIVATE_IN_PUBLIC);
151+
149152
// We have one lint pass defined specially
150153
store.register_late_pass(sess, false, box lint::GatherNodeLevels);
151154

src/librustc_mir/build/matches/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ struct ArmBlocks {
209209
}
210210

211211
#[derive(Clone, Debug)]
212-
struct Candidate<'pat, 'tcx:'pat> {
212+
pub struct Candidate<'pat, 'tcx:'pat> {
213213
// all of these must be satisfied...
214214
match_pairs: Vec<MatchPair<'pat, 'tcx>>,
215215

@@ -235,7 +235,7 @@ struct Binding<'tcx> {
235235
}
236236

237237
#[derive(Clone, Debug)]
238-
struct MatchPair<'pat, 'tcx:'pat> {
238+
pub struct MatchPair<'pat, 'tcx:'pat> {
239239
// this lvalue...
240240
lvalue: Lvalue<'tcx>,
241241

@@ -278,7 +278,7 @@ enum TestKind<'tcx> {
278278
}
279279

280280
#[derive(Debug)]
281-
struct Test<'tcx> {
281+
pub struct Test<'tcx> {
282282
span: Span,
283283
kind: TestKind<'tcx>,
284284
}

src/librustc_mir/build/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_front::hir;
1818
use syntax::ast;
1919
use syntax::codemap::Span;
2020

21-
struct Builder<'a, 'tcx: 'a> {
21+
pub struct Builder<'a, 'tcx: 'a> {
2222
hir: Cx<'a, 'tcx>,
2323
cfg: CFG<'tcx>,
2424
scopes: Vec<scope::Scope<'tcx>>,
@@ -40,7 +40,7 @@ struct CFG<'tcx> {
4040
// convenient.
4141

4242
#[must_use] // if you don't use one of these results, you're leaving a dangling edge
43-
struct BlockAnd<T>(BasicBlock, T);
43+
pub struct BlockAnd<T>(BasicBlock, T);
4444

4545
trait BlockAndExtension {
4646
fn and<T>(self, v: T) -> BlockAnd<T>;

src/librustc_privacy/diagnostics.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,14 @@ trait Foo {
2121
fn dummy(&self) { }
2222
}
2323
24-
pub trait Bar : Foo {} // error: private trait in exported type parameter bound
24+
pub trait Bar : Foo {} // error: private trait in public interface
2525
pub struct Bar<T: Foo>(pub T); // same error
2626
pub fn foo<T: Foo> (t: T) {} // same error
2727
```
2828
29-
To solve this error, please ensure that the trait is also public and accessible
30-
at the same level of the public functions or types which are bound on it.
29+
To solve this error, please ensure that the trait is also public. The trait
30+
can be made inaccessible if necessary by placing it into a private inner module,
31+
but it still has to be marked with `pub`.
3132
Example:
3233
3334
```
@@ -42,20 +43,22 @@ pub fn foo<T: Foo> (t: T) {} // ok!
4243
"##,
4344

4445
E0446: r##"
45-
A private type was used in an exported type signature. Erroneous code example:
46+
A private type was used in a public type signature. Erroneous code example:
4647
4748
```
4849
mod Foo {
4950
struct Bar(u32);
5051
51-
pub fn bar() -> Bar { // error: private type in exported type signature
52+
pub fn bar() -> Bar { // error: private type in public interface
5253
Bar(0)
5354
}
5455
}
5556
```
5657
57-
To solve this error, please ensure that the type is also public and accessible
58-
at the same level of the public functions or types which use it. Example:
58+
To solve this error, please ensure that the type is also public. The type
59+
can be made inaccessible if necessary by placing it into a private inner module,
60+
but it still has to be marked with `pub`.
61+
Example:
5962
6063
```
6164
mod Foo {

0 commit comments

Comments
 (0)