Skip to content

Commit d34b3e9

Browse files
committed
privacy: Account for associated existential types
1 parent daa53a5 commit d34b3e9

File tree

4 files changed

+59
-23
lines changed

4 files changed

+59
-23
lines changed

src/librustc_privacy/lib.rs

+26-17
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ extern crate rustc_typeck;
1313
extern crate syntax_pos;
1414
extern crate rustc_data_structures;
1515

16-
use rustc::hir::{self, Node, PatKind};
16+
use rustc::hir::{self, Node, PatKind, AssociatedItemKind};
1717
use rustc::hir::def::Def;
1818
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
1919
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
@@ -548,7 +548,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
548548
let mut reach = self.reach(trait_item_ref.id.node_id, item_level);
549549
reach.generics().predicates();
550550

551-
if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
551+
if trait_item_ref.kind == AssociatedItemKind::Type &&
552552
!trait_item_ref.defaultness.has_value() {
553553
// No type to visit.
554554
} else {
@@ -1333,11 +1333,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
13331333
if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
13341334
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
13351335
match impl_item_ref.kind {
1336-
hir::AssociatedItemKind::Const => {
1336+
AssociatedItemKind::Const => {
13371337
found_pub_static = true;
13381338
intravisit::walk_impl_item(self, impl_item);
13391339
}
1340-
hir::AssociatedItemKind::Method { has_self: false } => {
1340+
AssociatedItemKind::Method { has_self: false } => {
13411341
found_pub_static = true;
13421342
intravisit::walk_impl_item(self, impl_item);
13431343
}
@@ -1558,6 +1558,24 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
15581558
in_assoc_ty: false,
15591559
}
15601560
}
1561+
1562+
fn check_trait_or_impl_item(&self, node_id: ast::NodeId, assoc_item_kind: AssociatedItemKind,
1563+
defaultness: hir::Defaultness, vis: ty::Visibility) {
1564+
let mut check = self.check(node_id, vis);
1565+
1566+
let (check_ty, is_assoc_ty) = match assoc_item_kind {
1567+
AssociatedItemKind::Const | AssociatedItemKind::Method { .. } => (true, false),
1568+
AssociatedItemKind::Type => (defaultness.has_value(), true),
1569+
// `ty()` for existential types is the underlying type,
1570+
// it's not a part of interface, so we skip it.
1571+
AssociatedItemKind::Existential => (false, true),
1572+
};
1573+
check.in_assoc_ty = is_assoc_ty;
1574+
check.generics().predicates();
1575+
if check_ty {
1576+
check.ty();
1577+
}
1578+
}
15611579
}
15621580

15631581
impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
@@ -1592,16 +1610,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
15921610
self.check(item.id, item_visibility).generics().predicates();
15931611

15941612
for trait_item_ref in trait_item_refs {
1595-
let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
1596-
check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type;
1597-
check.generics().predicates();
1598-
1599-
if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
1600-
!trait_item_ref.defaultness.has_value() {
1601-
// No type to visit.
1602-
} else {
1603-
check.ty();
1604-
}
1613+
self.check_trait_or_impl_item(trait_item_ref.id.node_id, trait_item_ref.kind,
1614+
trait_item_ref.defaultness, item_visibility);
16051615
}
16061616
}
16071617
hir::ItemKind::TraitAlias(..) => {
@@ -1647,9 +1657,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
16471657
} else {
16481658
impl_vis
16491659
};
1650-
let mut check = self.check(impl_item.id, impl_item_vis);
1651-
check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
1652-
check.generics().predicates().ty();
1660+
self.check_trait_or_impl_item(impl_item_ref.id.node_id, impl_item_ref.kind,
1661+
impl_item_ref.defaultness, impl_item_vis);
16531662
}
16541663
}
16551664
}

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Private types and traits are not allowed in interfaces of associated types.
22
// This test also ensures that the checks are performed even inside private modules.
33

4-
#![feature(associated_type_defaults)]
4+
#![feature(associated_type_defaults, existential_type)]
55

66
mod m {
77
struct Priv;
@@ -23,10 +23,17 @@ mod m {
2323

2424
type Alias4 = Priv;
2525
//~^ ERROR private type `m::Priv` in public interface
26+
27+
type Exist;
28+
fn infer_exist() -> Self::Exist;
2629
}
2730
impl PubTr for u8 {
2831
type Alias1 = Priv;
2932
//~^ ERROR private type `m::Priv` in public interface
33+
34+
existential type Exist: PrivTr;
35+
//~^ ERROR private trait `m::PrivTr` in public interface
36+
fn infer_exist() -> Self::Exist { Priv }
3037
}
3138
}
3239

src/test/ui/privacy/private-in-public-assoc-ty.stderr

+15-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | | //~^ WARN private trait `m::PrivTr` in public interface
66
LL | | //~| WARN this was previously accepted
77
LL | | //~| WARN private type `m::Priv` in public interface
88
... |
9-
LL | | //~^ ERROR private type `m::Priv` in public interface
9+
LL | | fn infer_exist() -> Self::Exist;
1010
LL | | }
1111
| |_____^
1212
|
@@ -22,7 +22,7 @@ LL | | //~^ WARN private trait `m::PrivTr` in public interface
2222
LL | | //~| WARN this was previously accepted
2323
LL | | //~| WARN private type `m::Priv` in public interface
2424
... |
25-
LL | | //~^ ERROR private type `m::Priv` in public interface
25+
LL | | fn infer_exist() -> Self::Exist;
2626
LL | | }
2727
| |_____^
2828
|
@@ -39,14 +39,24 @@ LL | type Alias4 = Priv;
3939
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
4040

4141
error[E0446]: private type `m::Priv` in public interface
42-
--> $DIR/private-in-public-assoc-ty.rs:28:9
42+
--> $DIR/private-in-public-assoc-ty.rs:31:9
4343
|
4444
LL | struct Priv;
4545
| - `m::Priv` declared as private
4646
...
4747
LL | type Alias1 = Priv;
4848
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
4949

50-
error: aborting due to 2 previous errors
50+
error[E0445]: private trait `m::PrivTr` in public interface
51+
--> $DIR/private-in-public-assoc-ty.rs:34:9
52+
|
53+
LL | trait PrivTr {}
54+
| - `m::PrivTr` declared as private
55+
...
56+
LL | existential type Exist: PrivTr;
57+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
58+
59+
error: aborting due to 3 previous errors
5160

52-
For more information about this error, try `rustc --explain E0446`.
61+
Some errors occurred: E0445, E0446.
62+
For more information about an error, try `rustc --explain E0445`.

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

+10
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,14 @@ fn check() -> Pub {
1212
Priv
1313
}
1414

15+
pub trait Trait {
16+
type Pub: Default;
17+
fn method() -> Self::Pub;
18+
}
19+
20+
impl Trait for u8 {
21+
existential type Pub: Default;
22+
fn method() -> Self::Pub { Priv }
23+
}
24+
1525
fn main() {}

0 commit comments

Comments
 (0)