Skip to content

Commit c6209a3

Browse files
committed
Always report private-in-public in associated types as hard errors
according to RFC 2145. Fix a silly label message.
1 parent 020961d commit c6209a3

File tree

7 files changed

+108
-31
lines changed

7 files changed

+108
-31
lines changed

src/librustc_privacy/lib.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
13131313
min_visibility: ty::Visibility,
13141314
has_pub_restricted: bool,
13151315
has_old_errors: bool,
1316+
in_assoc_ty: bool,
13161317
}
13171318

13181319
impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
@@ -1373,11 +1374,11 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
13731374
self.min_visibility = vis;
13741375
}
13751376
if !vis.is_at_least(self.required_visibility, self.tcx) {
1376-
if self.has_pub_restricted || self.has_old_errors {
1377+
if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
13771378
struct_span_err!(self.tcx.sess, self.span, E0445,
13781379
"private trait `{}` in public interface", trait_ref)
13791380
.span_label(self.span, format!(
1380-
"private trait can't be public"))
1381+
"can't leak private trait"))
13811382
.emit();
13821383
} else {
13831384
self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC,
@@ -1428,7 +1429,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
14281429
self.min_visibility = vis;
14291430
}
14301431
if !vis.is_at_least(self.required_visibility, self.tcx) {
1431-
if self.has_pub_restricted || self.has_old_errors {
1432+
if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
14321433
let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
14331434
"private type `{}` in public interface", ty);
14341435
err.span_label(self.span, "can't leak private type");
@@ -1489,6 +1490,7 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
14891490
required_visibility,
14901491
has_pub_restricted: self.has_pub_restricted,
14911492
has_old_errors,
1493+
in_assoc_ty: false,
14921494
}
14931495
}
14941496
}
@@ -1529,6 +1531,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
15291531

15301532
for trait_item_ref in trait_item_refs {
15311533
let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
1534+
check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type;
15321535
check.generics().predicates();
15331536

15341537
if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
@@ -1579,10 +1582,10 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
15791582

15801583
for impl_item_ref in impl_item_refs {
15811584
let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
1582-
let impl_item_vis =
1583-
ty::Visibility::from_hir(&impl_item.vis, item.id, tcx);
1584-
self.check(impl_item.id, min(impl_item_vis, ty_vis))
1585-
.generics().predicates().ty();
1585+
let impl_item_vis = ty::Visibility::from_hir(&impl_item.vis, item.id, tcx);
1586+
let mut check = self.check(impl_item.id, min(impl_item_vis, ty_vis));
1587+
check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
1588+
check.generics().predicates().ty();
15861589

15871590
// Recurse for e.g. `impl Trait` (see `visit_ty`).
15881591
self.inner_visibility = impl_item_vis;
@@ -1597,7 +1600,9 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
15971600
self.check(item.id, vis).generics().predicates();
15981601
for impl_item_ref in impl_item_refs {
15991602
let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
1600-
self.check(impl_item.id, vis).generics().predicates().ty();
1603+
let mut check = self.check(impl_item.id, vis);
1604+
check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
1605+
check.generics().predicates().ty();
16011606

16021607
// Recurse for e.g. `impl Trait` (see `visit_ty`).
16031608
self.inner_visibility = vis;

src/test/compile-fail/E0445.rs

+3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,12 @@ trait Foo {
1414

1515
pub trait Bar : Foo {}
1616
//~^ ERROR private trait `Foo` in public interface [E0445]
17+
//~| NOTE can't leak private trait
1718
pub struct Bar2<T: Foo>(pub T);
1819
//~^ ERROR private trait `Foo` in public interface [E0445]
20+
//~| NOTE can't leak private trait
1921
pub fn foo<T: Foo> (t: T) {}
2022
//~^ ERROR private trait `Foo` in public interface [E0445]
23+
//~| NOTE can't leak private trait
2124

2225
fn main() {}

src/test/compile-fail/issue-30079.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,12 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
#![deny(private_in_public)]
12-
#![allow(unused)]
13-
1411
struct SemiPriv;
1512

1613
mod m1 {
1714
struct Priv;
1815
impl ::SemiPriv {
19-
pub fn f(_: Priv) {} //~ ERROR private type `m1::Priv` in public interface
16+
pub fn f(_: Priv) {} //~ WARN private type `m1::Priv` in public interface
2017
//~^ WARNING hard error
2118
}
2219

@@ -29,7 +26,6 @@ mod m2 {
2926
struct Priv;
3027
impl ::std::ops::Deref for ::SemiPriv {
3128
type Target = Priv; //~ ERROR private type `m2::Priv` in public interface
32-
//~^ WARNING hard error
3329
fn deref(&self) -> &Self::Target { unimplemented!() }
3430
}
3531

@@ -47,7 +43,6 @@ mod m3 {
4743
struct Priv;
4844
impl ::SemiPrivTrait for () {
4945
type Assoc = Priv; //~ ERROR private type `m3::Priv` in public interface
50-
//~^ WARNING hard error
5146
}
5247
}
5348

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Private types and traits are not allowed in interfaces of associated types.
12+
// This test also ensures that the checks are performed even inside private modules.
13+
14+
#![feature(associated_type_defaults)]
15+
16+
mod m {
17+
struct Priv;
18+
trait PrivTr {}
19+
impl PrivTr for Priv {}
20+
pub trait PubTrAux1<T> {}
21+
pub trait PubTrAux2 { type A; }
22+
23+
// "Private-in-public in associated types is hard error" in RFC 2145
24+
// applies only to the aliased types, not bounds.
25+
pub trait PubTr {
26+
//~^ WARN private trait `m::PrivTr` in public interface
27+
//~| WARN this was previously accepted
28+
//~| WARN private type `m::Priv` in public interface
29+
//~| WARN this was previously accepted
30+
type Alias1: PrivTr;
31+
type Alias2: PubTrAux1<Priv> = u8;
32+
type Alias3: PubTrAux2<A = Priv> = u8;
33+
34+
type Alias4 = Priv;
35+
//~^ ERROR private type `m::Priv` in public interface
36+
}
37+
impl PubTr for u8 {
38+
type Alias1 = Priv;
39+
//~^ ERROR private type `m::Priv` in public interface
40+
}
41+
}
42+
43+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
mod aliases_pub {
12+
struct Priv;
13+
mod m {
14+
pub struct Pub3;
15+
}
16+
17+
trait PrivTr {
18+
type AssocAlias;
19+
}
20+
impl PrivTr for Priv {
21+
type AssocAlias = m::Pub3;
22+
}
23+
24+
impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
25+
pub fn f(arg: Priv) {} // private type `aliases_pub::Priv` in public interface
26+
}
27+
}
28+
29+
mod aliases_priv {
30+
struct Priv;
31+
struct Priv3;
32+
33+
trait PrivTr {
34+
type AssocAlias;
35+
}
36+
impl PrivTr for Priv {
37+
type AssocAlias = Priv3;
38+
}
39+
40+
impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
41+
pub fn f(arg: Priv) {} // OK
42+
}
43+
}
44+
45+
fn main() {}

src/test/compile-fail/private-in-public-warn.rs

-15
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313

1414
#![feature(associated_type_defaults)]
1515
#![deny(private_in_public)]
16-
#![allow(unused)]
1716
#![allow(improper_ctypes)]
1817

1918
mod types {
@@ -35,7 +34,6 @@ mod types {
3534
const C: Priv = Priv; //~ ERROR private type `types::Priv` in public interface
3635
//~^ WARNING hard error
3736
type Alias = Priv; //~ ERROR private type `types::Priv` in public interface
38-
//~^ WARNING hard error
3937
fn f1(arg: Priv) {} //~ ERROR private type `types::Priv` in public interface
4038
//~^ WARNING hard error
4139
fn f2() -> Priv { panic!() } //~ ERROR private type `types::Priv` in public interface
@@ -51,7 +49,6 @@ mod types {
5149
}
5250
impl PubTr for Pub {
5351
type Alias = Priv; //~ ERROR private type `types::Priv` in public interface
54-
//~^ WARNING hard error
5552
}
5653
}
5754

@@ -146,7 +143,6 @@ mod impls {
146143
}
147144
impl PubTr for Pub {
148145
type Alias = Priv; //~ ERROR private type `impls::Priv` in public interface
149-
//~^ WARNING hard error
150146
}
151147
}
152148

@@ -220,21 +216,14 @@ mod aliases_pub {
220216
pub fn f(arg: Priv) {} //~ ERROR private type `aliases_pub::Priv` in public interface
221217
//~^ WARNING hard error
222218
}
223-
// This doesn't even parse
224-
// impl <Priv as PrivTr>::AssocAlias {
225-
// pub fn f(arg: Priv) {} // ERROR private type `aliases_pub::Priv` in public interface
226-
// }
227219
impl PrivUseAliasTr for PrivUseAlias {
228220
type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
229-
//~^ WARNING hard error
230221
}
231222
impl PrivUseAliasTr for PrivAlias {
232223
type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
233-
//~^ WARNING hard error
234224
}
235225
impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
236226
type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
237-
//~^ WARNING hard error
238227
}
239228
}
240229

@@ -273,10 +262,6 @@ mod aliases_priv {
273262
impl PrivAlias {
274263
pub fn f(arg: Priv) {} // OK
275264
}
276-
// This doesn't even parse
277-
// impl <Priv as PrivTr>::AssocAlias {
278-
// pub fn f(arg: Priv) {} // OK
279-
// }
280265
impl PrivUseAliasTr for PrivUseAlias {
281266
type Check = Priv; // OK
282267
}

src/test/compile-fail/private-inferred-type.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#![feature(associated_consts)]
1212
#![feature(conservative_impl_trait)]
1313
#![feature(decl_macro)]
14-
#![allow(warnings)]
14+
#![allow(private_in_public)]
1515

1616
mod m {
1717
fn priv_fn() {}
@@ -70,6 +70,7 @@ mod m {
7070
impl<T> TraitWithTyParam<T> for u8 {}
7171
impl TraitWithTyParam2<Priv> for u8 {}
7272
impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
73+
//~^ ERROR private type `m::Priv` in public interface
7374

7475
pub fn leak_anon1() -> impl Trait + 'static { 0 }
7576
pub fn leak_anon2() -> impl TraitWithTyParam<Alias> { 0 }
@@ -90,7 +91,7 @@ mod adjust {
9091
pub struct S3;
9192

9293
impl Deref for S1 {
93-
type Target = S2Alias;
94+
type Target = S2Alias; //~ ERROR private type `adjust::S2` in public interface
9495
fn deref(&self) -> &Self::Target { loop {} }
9596
}
9697
impl Deref for S2 {

0 commit comments

Comments
 (0)