Skip to content

Commit fe6a54d

Browse files
committed
Auto merge of #56878 - petrochenkov:privdyn, r=arielb1
privacy: Use common `DefId` visiting infrastructure for all privacy visitors One repeating pattern in privacy checking is going through a type, visiting all `DefId`s inside it and doing something with them. This is the case because visibilities and reachabilities are attached to `DefId`s. Previously various privacy visitors visited types slightly differently using their own methods, with most recently written `TypePrivacyVisitor` being the "gold standard". This mostly worked okay, but differences could manifest in overly conservative reachability analysis, some errors being reported twice, some private-in-public lints (not errors) being wrongly reported or not reported. This PR does something that I wanted to do since #32674 (comment) - factoring out the common visiting logic! Now all the common logic is contained in `struct DefIdVisitorSkeleton`, with specific privacy visitors deciding only what to do with visited `DefId`s (via `trait DefIdVisitor`). A bunch of cleanups is also applied in the process. This area is somewhat tricky due to lots of easily miss-able details, but thankfully it's was well covered by tests in #46083 and previous PRs, so I'm relatively sure in the refactoring correctness. Fixes #56837 (comment) in particular. Also this will help with implementing #48054.
2 parents 9eac386 + 60d1fa7 commit fe6a54d

22 files changed

+621
-559
lines changed

src/librustc/hir/mod.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,15 @@ impl VisibilityKind {
20902090
VisibilityKind::Restricted { .. } => true,
20912091
}
20922092
}
2093+
2094+
pub fn descr(&self) -> &'static str {
2095+
match *self {
2096+
VisibilityKind::Public => "public",
2097+
VisibilityKind::Inherited => "private",
2098+
VisibilityKind::Crate(..) => "crate-visible",
2099+
VisibilityKind::Restricted { .. } => "restricted",
2100+
}
2101+
}
20932102
}
20942103

20952104
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]

src/librustc/util/ppaux.rs

+3
Original file line numberDiff line numberDiff line change
@@ -709,6 +709,9 @@ define_print! {
709709

710710
define_print! {
711711
('tcx) ty::ExistentialTraitRef<'tcx>, (self, f, cx) {
712+
display {
713+
cx.parameterized(f, self.substs, self.def_id, &[])
714+
}
712715
debug {
713716
ty::tls::with(|tcx| {
714717
let dummy_self = tcx.mk_infer(ty::FreshTy(0));

src/librustc_privacy/lib.rs

+446-514
Large diffs are not rendered by default.

src/libstd/sys/windows/handle.rs

-5
Original file line numberDiff line numberDiff line change
@@ -160,11 +160,6 @@ impl RawHandle {
160160
}
161161
}
162162

163-
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
164-
let mut me = self;
165-
(&mut me).read_to_end(buf)
166-
}
167-
168163
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
169164
let mut amt = 0;
170165
let len = cmp::min(buf.len(), <c::DWORD>::max_value() as usize) as c::DWORD;

src/libstd/sys/windows/stdio.rs

-5
Original file line numberDiff line numberDiff line change
@@ -128,11 +128,6 @@ impl Stdin {
128128
// MemReader shouldn't error here since we just filled it
129129
utf8.read(buf)
130130
}
131-
132-
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
133-
let mut me = self;
134-
(&mut me).read_to_end(buf)
135-
}
136131
}
137132

138133
#[unstable(reason = "not public", issue = "0", feature = "fd_read")]

src/test/ui/error-codes/E0445.rs

-3
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,9 @@ trait Foo {
44

55
pub trait Bar : Foo {}
66
//~^ ERROR private trait `Foo` in public interface [E0445]
7-
//~| NOTE can't leak private trait
87
pub struct Bar2<T: Foo>(pub T);
98
//~^ ERROR private trait `Foo` in public interface [E0445]
10-
//~| NOTE can't leak private trait
119
pub fn foo<T: Foo> (t: T) {}
1210
//~^ ERROR private trait `Foo` in public interface [E0445]
13-
//~| NOTE can't leak private trait
1411

1512
fn main() {}

src/test/ui/error-codes/E0445.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ LL | pub trait Bar : Foo {}
55
| ^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
66

77
error[E0445]: private trait `Foo` in public interface
8-
--> $DIR/E0445.rs:8:1
8+
--> $DIR/E0445.rs:7:1
99
|
1010
LL | pub struct Bar2<T: Foo>(pub T);
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
1212

1313
error[E0445]: private trait `Foo` in public interface
14-
--> $DIR/E0445.rs:11:1
14+
--> $DIR/E0445.rs:9:1
1515
|
1616
LL | pub fn foo<T: Foo> (t: T) {}
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait

src/test/ui/impl-trait/issue-49376.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ fn gen() -> impl PartialOrd + PartialEq + Debug { }
99

1010
struct Bar {}
1111
trait Foo<T = Self> {}
12+
trait FooNested<T = Option<Self>> {}
1213
impl Foo for Bar {}
14+
impl FooNested for Bar {}
1315

14-
fn foo() -> impl Foo {
16+
fn foo() -> impl Foo + FooNested {
1517
Bar {}
1618
}
1719

src/test/ui/issues/issue-18389.stderr

+3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
error[E0445]: private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface
22
--> $DIR/issue-18389.rs:7:1
33
|
4+
LL | trait Private<P, R> {
5+
| - `Private<<Self as Public>::P, <Self as Public>::R>` declared as private
6+
...
47
LL | / pub trait Public: Private<
58
LL | | //~^ ERROR private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface
69
LL | | <Self as Public>::P,

src/test/ui/privacy/associated-item-privacy-type-binding.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ mod priv_trait {
99

1010
pub macro mac1() {
1111
let _: Box<PubTr<AssocTy = u8>>;
12-
//~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private
13-
//~| ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private
12+
//~^ ERROR trait `priv_trait::PrivTr` is private
13+
//~| ERROR trait `priv_trait::PrivTr` is private
1414
type InSignatureTy2 = Box<PubTr<AssocTy = u8>>;
15-
//~^ ERROR type `(dyn priv_trait::PubTr<AssocTy=u8> + 'static)` is private
15+
//~^ ERROR trait `priv_trait::PrivTr` is private
1616
trait InSignatureTr2: PubTr<AssocTy = u8> {}
1717
//~^ ERROR trait `priv_trait::PrivTr` is private
1818
}
1919
pub macro mac2() {
2020
let _: Box<PrivTr<AssocTy = u8>>;
21-
//~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private
22-
//~| ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private
21+
//~^ ERROR trait `priv_trait::PrivTr` is private
22+
//~| ERROR trait `priv_trait::PrivTr` is private
2323
type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>;
24-
//~^ ERROR type `(dyn priv_trait::PrivTr<AssocTy=u8> + 'static)` is private
24+
//~^ ERROR trait `priv_trait::PrivTr` is private
2525
trait InSignatureTr1: PrivTr<AssocTy = u8> {}
2626
//~^ ERROR trait `priv_trait::PrivTr` is private
2727
}

src/test/ui/privacy/associated-item-privacy-type-binding.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private
1+
error: trait `priv_trait::PrivTr` is private
22
--> $DIR/associated-item-privacy-type-binding.rs:11:13
33
|
44
LL | let _: Box<PubTr<AssocTy = u8>>;
@@ -7,7 +7,7 @@ LL | let _: Box<PubTr<AssocTy = u8>>;
77
LL | priv_trait::mac1!();
88
| -------------------- in this macro invocation
99

10-
error: type `(dyn priv_trait::PubTr<AssocTy=u8> + '<empty>)` is private
10+
error: trait `priv_trait::PrivTr` is private
1111
--> $DIR/associated-item-privacy-type-binding.rs:11:16
1212
|
1313
LL | let _: Box<PubTr<AssocTy = u8>>;
@@ -16,7 +16,7 @@ LL | let _: Box<PubTr<AssocTy = u8>>;
1616
LL | priv_trait::mac1!();
1717
| -------------------- in this macro invocation
1818

19-
error: type `(dyn priv_trait::PubTr<AssocTy=u8> + 'static)` is private
19+
error: trait `priv_trait::PrivTr` is private
2020
--> $DIR/associated-item-privacy-type-binding.rs:14:31
2121
|
2222
LL | type InSignatureTy2 = Box<PubTr<AssocTy = u8>>;
@@ -34,7 +34,7 @@ LL | trait InSignatureTr2: PubTr<AssocTy = u8> {}
3434
LL | priv_trait::mac1!();
3535
| -------------------- in this macro invocation
3636

37-
error: type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private
37+
error: trait `priv_trait::PrivTr` is private
3838
--> $DIR/associated-item-privacy-type-binding.rs:20:13
3939
|
4040
LL | let _: Box<PrivTr<AssocTy = u8>>;
@@ -43,7 +43,7 @@ LL | let _: Box<PrivTr<AssocTy = u8>>;
4343
LL | priv_trait::mac2!();
4444
| -------------------- in this macro invocation
4545

46-
error: type `(dyn priv_trait::PrivTr<AssocTy=u8> + '<empty>)` is private
46+
error: trait `priv_trait::PrivTr` is private
4747
--> $DIR/associated-item-privacy-type-binding.rs:20:16
4848
|
4949
LL | let _: Box<PrivTr<AssocTy = u8>>;
@@ -52,7 +52,7 @@ LL | let _: Box<PrivTr<AssocTy = u8>>;
5252
LL | priv_trait::mac2!();
5353
| -------------------- in this macro invocation
5454

55-
error: type `(dyn priv_trait::PrivTr<AssocTy=u8> + 'static)` is private
55+
error: trait `priv_trait::PrivTr` is private
5656
--> $DIR/associated-item-privacy-type-binding.rs:23:31
5757
|
5858
LL | type InSignatureTy1 = Box<PrivTr<AssocTy = u8>>;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Patterns and expressions are not interface parts and don't produce private-in-public errors.
2+
3+
// compile-pass
4+
5+
struct Priv1(usize);
6+
struct Priv2;
7+
8+
pub struct Pub(Priv2);
9+
10+
pub fn public_expr(_: [u8; Priv1(0).0]) {} // OK
11+
pub fn public_pat(Pub(Priv2): Pub) {} // OK
12+
13+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(optin_builtin_traits)]
2+
3+
#[allow(private_in_public)]
4+
mod m {
5+
pub trait PubPrincipal {}
6+
auto trait PrivNonPrincipal {}
7+
pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} }
8+
}
9+
10+
fn main() {
11+
m::leak_dyn_nonprincipal();
12+
//~^ ERROR trait `m::PrivNonPrincipal` is private
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
error: trait `m::PrivNonPrincipal` is private
2+
--> $DIR/private-in-public-non-principal-2.rs:11:5
3+
|
4+
LL | m::leak_dyn_nonprincipal();
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: aborting due to previous error
8+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#![feature(optin_builtin_traits)]
2+
3+
pub trait PubPrincipal {}
4+
auto trait PrivNonPrincipal {}
5+
6+
pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} }
7+
//~^ WARN private trait `PrivNonPrincipal` in public interface
8+
//~| WARN this was previously accepted
9+
10+
#[deny(missing_docs)]
11+
fn container() {
12+
impl dyn PubPrincipal {
13+
pub fn check_doc_lint() {} //~ ERROR missing documentation for a method
14+
}
15+
impl dyn PubPrincipal + PrivNonPrincipal {
16+
pub fn check_doc_lint() {} // OK, no missing doc lint
17+
}
18+
}
19+
20+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
warning: private trait `PrivNonPrincipal` in public interface (error E0445)
2+
--> $DIR/private-in-public-non-principal.rs:6:1
3+
|
4+
LL | pub fn leak_dyn_nonprincipal() -> Box<PubPrincipal + PrivNonPrincipal> { loop {} }
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: #[warn(private_in_public)] on by default
8+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
9+
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
10+
11+
error: missing documentation for a method
12+
--> $DIR/private-in-public-non-principal.rs:13:9
13+
|
14+
LL | pub fn check_doc_lint() {} //~ ERROR missing documentation for a method
15+
| ^^^^^^^^^^^^^^^^^^^^^^^
16+
|
17+
note: lint level defined here
18+
--> $DIR/private-in-public-non-principal.rs:10:8
19+
|
20+
LL | #[deny(missing_docs)]
21+
| ^^^^^^^^^^^^
22+
23+
error: aborting due to previous error
24+

src/test/ui/privacy/private-in-public-warn.rs

+9
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,15 @@ mod aliases_pub {
213213
impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
214214
type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
215215
}
216+
impl PrivUseAliasTr for Option<<Priv as PrivTr>::AssocAlias> {
217+
type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
218+
}
219+
impl PrivUseAliasTr for (<Priv as PrivTr>::AssocAlias, Priv) {
220+
type Check = Priv; // OK
221+
}
222+
impl PrivUseAliasTr for Option<(<Priv as PrivTr>::AssocAlias, Priv)> {
223+
type Check = Priv; // OK
224+
}
216225
}
217226

218227
mod aliases_priv {

src/test/ui/privacy/private-in-public-warn.stderr

+15-6
Original file line numberDiff line numberDiff line change
@@ -297,33 +297,42 @@ LL | struct Priv;
297297
LL | type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
298298
| ^^^^^^^^^^^^^^^^^^ can't leak private type
299299

300+
error[E0446]: private type `aliases_pub::Priv` in public interface
301+
--> $DIR/private-in-public-warn.rs:217:9
302+
|
303+
LL | struct Priv;
304+
| - `aliases_pub::Priv` declared as private
305+
...
306+
LL | type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
307+
| ^^^^^^^^^^^^^^^^^^ can't leak private type
308+
300309
error: private trait `aliases_priv::PrivTr1` in public interface (error E0445)
301-
--> $DIR/private-in-public-warn.rs:238:5
310+
--> $DIR/private-in-public-warn.rs:247:5
302311
|
303312
LL | pub trait Tr1: PrivUseAliasTr {}
304313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
305314
|
306315
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
307316
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
308317

309-
error: private type `aliases_priv::Priv2` in public interface (error E0446)
310-
--> $DIR/private-in-public-warn.rs:241:5
318+
error: private trait `aliases_priv::PrivTr1<aliases_priv::Priv2>` in public interface (error E0445)
319+
--> $DIR/private-in-public-warn.rs:250:5
311320
|
312321
LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
313322
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
314323
|
315324
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
316325
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
317326

318-
error: private trait `aliases_priv::PrivTr1<aliases_priv::Priv2>` in public interface (error E0445)
319-
--> $DIR/private-in-public-warn.rs:241:5
327+
error: private type `aliases_priv::Priv2` in public interface (error E0446)
328+
--> $DIR/private-in-public-warn.rs:250:5
320329
|
321330
LL | pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
322331
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
323332
|
324333
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
325334
= note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537>
326335

327-
error: aborting due to 35 previous errors
336+
error: aborting due to 36 previous errors
328337

329338
For more information about this error, try `rustc --explain E0446`.

src/test/ui/privacy/private-in-public.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ mod aliases_pub {
102102

103103
// This should be OK, but associated type aliases are not substituted yet
104104
pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
105-
//~^ ERROR private type `<aliases_pub::Priv as aliases_pub::PrivTr>::Assoc` in public interface
105+
//~^ ERROR private trait `aliases_pub::PrivTr` in public interface
106106
//~| ERROR private type `aliases_pub::Priv` in public interface
107107

108108
impl PrivUseAlias {
@@ -131,7 +131,7 @@ mod aliases_priv {
131131
pub fn f1(arg: PrivUseAlias) {} //~ ERROR private type `aliases_priv::Priv1` in public interface
132132
pub fn f2(arg: PrivAlias) {} //~ ERROR private type `aliases_priv::Priv2` in public interface
133133
pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
134-
//~^ ERROR private type `<aliases_priv::Priv as aliases_priv::PrivTr>::Assoc` in public
134+
//~^ ERROR private trait `aliases_priv::PrivTr` in public interface
135135
//~| ERROR private type `aliases_priv::Priv` in public interface
136136
}
137137

0 commit comments

Comments
 (0)